From 5036b996d76599c8fe9f71ab90290078e2396382 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 18 Dec 2025 20:46:26 +0200 Subject: [PATCH 001/137] Late materialization golden tests --- x-pack/plugin/esql/build.gradle | 7 +- ...ductionLateMaterializationGoldenTests.java | 37 +++++ .../esql/plan/physical/FragmentExec.java | 2 +- .../xpack/esql/plugin/ComputeService.java | 3 +- .../xpack/esql/plugin/ReductionPlan.java | 3 +- .../xpack/esql/optimizer/GoldenTestCase.java | 120 +++++++++++--- ...LateMaterializationPlannerGoldenTests.java | 154 ++++++++++++++++++ .../physical_optimization.expected | 7 + .../reduction_data.expected | 5 + .../reduction_local_data.expected | 4 + .../reduction_local_node_reduce.expected | 5 + .../reduction_node_reduce.expected | 5 + .../physical_optimization.expected | 8 + .../reduction_data.expected | 6 + .../reduction_local_data.expected | 6 + .../reduction_local_node_reduce.expected | 5 + .../reduction_node_reduce.expected | 5 + .../physical_optimization.expected | 10 ++ .../reduction_data.expected | 9 + .../reduction_local_data.expected | 25 +++ .../reduction_local_node_reduce.expected | 5 + .../reduction_node_reduce.expected | 5 + .../physical_optimization.expected | 7 + .../reduction_data.expected | 5 + .../reduction_local_data.expected | 4 + .../reduction_local_node_reduce.expected | 5 + .../reduction_node_reduce.expected | 5 + .../physical_optimization.expected | 8 + .../testMultipleTopN/reduction_data.expected | 5 + .../reduction_local_data.expected | 4 + .../reduction_local_node_reduce.expected | 5 + .../reduction_node_reduce.expected | 5 + .../physical_optimization.expected | 8 + .../reduction_data.expected | 7 + .../reduction_local_data.expected | 7 + .../reduction_local_node_reduce.expected | 3 + .../reduction_node_reduce.expected | 3 + .../physical_optimization.expected | 7 + .../reduction_data.expected | 5 + .../reduction_local_data.expected | 4 + .../reduction_local_node_reduce.expected | 5 + .../reduction_node_reduce.expected | 5 + .../physical_optimization.expected | 8 + .../reduction_data.expected | 6 + .../reduction_local_data.expected | 17 ++ .../reduction_local_node_reduce.expected | 5 + .../reduction_node_reduce.expected | 5 + .../physical_optimization.expected | 10 ++ .../testTopNThenStats/reduction_data.expected | 5 + .../reduction_local_data.expected | 4 + .../reduction_local_node_reduce.expected | 5 + .../reduction_node_reduce.expected | 5 + .../physical_optimization.expected | 7 + .../reduction_data.expected | 5 + .../reduction_local_data.expected | 4 + .../reduction_local_node_reduce.expected | 5 + .../reduction_node_reduce.expected | 5 + 57 files changed, 613 insertions(+), 26 deletions(-) create mode 100644 x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlReductionLateMaterializationGoldenTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlannerGoldenTests.java create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_local_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_local_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_local_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_local_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_local_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_local_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_local_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_local_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_local_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_local_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_local_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_local_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_local_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_local_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_local_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_local_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_local_data.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_local_node_reduce.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_node_reduce.expected diff --git a/x-pack/plugin/esql/build.gradle b/x-pack/plugin/esql/build.gradle index 620e941e8c4c6..35346969e8f23 100644 --- a/x-pack/plugin/esql/build.gradle +++ b/x-pack/plugin/esql/build.gradle @@ -626,12 +626,13 @@ tasks.named("test").configure { if (System.getProperty("golden.noactual") != null || project.hasProperty("golden.noactual")) { systemProperty "golden.noactual", "true" } - if (System.getProperty("golden.cleanactual") != null || project.hasProperty("golden.cleanactual")) { - systemProperty "golden.cleanactual", "true" - } if (System.getProperty("golden.overwrite") != null || project.hasProperty("golden.overwrite")) { systemProperty "golden.overwrite", "true" } + if (System.getProperty("golden.cleanactual") != null || project.hasProperty("golden.cleanactual")) { + systemProperty "golden.cleanactual", "true" + } + systemProperty "policy.directory", file("${projectDir}").absolutePath systemProperty "java.security.policy", file("${projectDir}/test.policy").absolutePath } diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlReductionLateMaterializationGoldenTests.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlReductionLateMaterializationGoldenTests.java new file mode 100644 index 0000000000000..015676ebb099d --- /dev/null +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlReductionLateMaterializationGoldenTests.java @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.action; + +import org.elasticsearch.xpack.esql.optimizer.GoldenTestCase; + +import java.util.EnumSet; + +public class EsqlReductionLateMaterializationGoldenTests extends GoldenTestCase { + /* + For instance, I'd like to see the data (and reduce) plans for cases such as: + queries with more than 1 topn + queries that have mv_expand (known problem due to preventing projections from bubbling up) + queries that have lookup joins on the data node + queries that have subsequent reducers that should end up on the coordinator (e.g. topn first, then stats) + queries where some fields need to be extracted before the topn, and others don't + queries where the topn sorts on expressions and/or sorts on more than 1 field + queries where the topn can be pushed down to Lucene in the data node plan, and queries where this isn't possible. + queries where the fields required for the TopN are missing on the data node (interactions with ReplaceFieldWithConstantOrNull can be subtle and only pop up as bugs months later) + */ + + public void testMultipleTopN() throws Exception { + String query = """ + FROM employees + | SORT hire_date + | LIMIT 20 + | SORT salary + | LIMIT 10 + """; + runGoldenTest(query, EnumSet.of(Stage.NODE_REDUCE)); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/physical/FragmentExec.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/physical/FragmentExec.java index 35667bdaf00a2..c1a642817fad7 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/physical/FragmentExec.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/physical/FragmentExec.java @@ -137,7 +137,7 @@ public String nodeString(NodeStringFormat format) { sb.append(estimatedRowSize); sb.append(", reducer=["); sb.append("], fragment=[<>\n"); - sb.append(fragment.toString()); + sb.append(fragment.toString(format)); sb.append("<>]]"); return sb.toString(); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeService.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeService.java index e5e06f6392ea5..5fd6ccea54f24 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeService.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeService.java @@ -758,7 +758,8 @@ ActionListener addCompletionInfo( }); } - static ReductionPlan reductionPlan( + // public for testing + public static ReductionPlan reductionPlan( PlannerSettings plannerSettings, EsqlFlags flags, Configuration configuration, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ReductionPlan.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ReductionPlan.java index 965762d127413..9e7ee12aa3e03 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ReductionPlan.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ReductionPlan.java @@ -10,10 +10,11 @@ import org.elasticsearch.xpack.esql.plan.physical.ExchangeSinkExec; /** + * This class is {@code public} for testing. * @param nodeReducePlan The plan to be executed on the node_reduce driver. This should not contain a * {@link org.elasticsearch.xpack.esql.plan.physical.FragmentExec}, but be a plan "sandwiched" between an {@link ExchangeSinkExec} and an * {@link org.elasticsearch.xpack.esql.plan.physical.ExchangeSourceExec}. * @param dataNodePlan The plan to be executed on the data driver. This may contain a * {@link org.elasticsearch.xpack.esql.plan.physical.FragmentExec}. */ -record ReductionPlan(ExchangeSinkExec nodeReducePlan, ExchangeSinkExec dataNodePlan) {} +public record ReductionPlan(ExchangeSinkExec nodeReducePlan, ExchangeSinkExec dataNodePlan) {} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index b382d2916c095..8a3150f24e877 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -31,10 +31,14 @@ import org.elasticsearch.xpack.esql.parser.EsqlParser; import org.elasticsearch.xpack.esql.plan.QueryPlan; import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; +import org.elasticsearch.xpack.esql.plan.physical.ExchangeExec; +import org.elasticsearch.xpack.esql.plan.physical.ExchangeSinkExec; import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; import org.elasticsearch.xpack.esql.planner.PlannerUtils; import org.elasticsearch.xpack.esql.planner.mapper.Mapper; +import org.elasticsearch.xpack.esql.plugin.ComputeService; import org.elasticsearch.xpack.esql.plugin.EsqlFlags; +import org.elasticsearch.xpack.esql.plugin.ReductionPlan; import org.elasticsearch.xpack.esql.session.Configuration; import org.elasticsearch.xpack.esql.session.Versioned; import org.elasticsearch.xpack.esql.stats.SearchStats; @@ -78,6 +82,10 @@ public GoldenTestCase() { } + protected void runGoldenTest(String esqlQuery, EnumSet stages, String... nestedPath) { + runGoldenTest(esqlQuery, stages, EsqlTestUtils.TEST_SEARCH_STATS, nestedPath); + } + protected void runGoldenTest(String esqlQuery, EnumSet stages, SearchStats searchStats, String... nestedPath) { String testName = extractTestName(); new Test(baseFile, testName, nestedPath, esqlQuery, stages, searchStats).doTest(); @@ -185,59 +193,128 @@ private List> doTests() throws IOException { if (stages.contains(Stage.LOGICAL_OPTIMIZATION)) { result.add(Tuple.tuple(Stage.LOGICAL_OPTIMIZATION, verifyOrWrite(logicallyOptimized, Stage.LOGICAL_OPTIMIZATION))); } - if (stages.contains(Stage.PHYSICAL_OPTIMIZATION) || stages.contains(Stage.LOCAL_PHYSICAL_OPTIMIZATION)) { + if (stages.contains(Stage.PHYSICAL_OPTIMIZATION) + || stages.contains(Stage.LOCAL_PHYSICAL_OPTIMIZATION) + || stages.contains(Stage.NODE_REDUCE_OPTIMIZATION) + || stages.contains(Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION)) { var physicalPlanOptimizer = new PhysicalPlanOptimizer(new PhysicalOptimizerContext(null, null)); PhysicalPlan physicalPlan = physicalPlanOptimizer.optimize(new Mapper().map(new Versioned<>(logicallyOptimized, version))); if (stages.contains(Stage.PHYSICAL_OPTIMIZATION)) { result.add(Tuple.tuple(Stage.PHYSICAL_OPTIMIZATION, verifyOrWrite(physicalPlan, Stage.PHYSICAL_OPTIMIZATION))); } + Configuration conf = analyzer.context().configuration(); if (stages.contains(Stage.LOCAL_PHYSICAL_OPTIMIZATION)) { - Configuration conf = analyzer.context().configuration(); - var localPhysicalPlan = PlannerUtils.localPlan( + TestResult localPhysicalResult = verifyOrWrite(localOptimize(physicalPlan, conf), Stage.LOCAL_PHYSICAL_OPTIMIZATION); + result.add(Tuple.tuple(Stage.LOCAL_PHYSICAL_OPTIMIZATION, localPhysicalResult)); + } + if (stages.contains(Stage.NODE_REDUCE_OPTIMIZATION) || stages.contains(Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION)) { + ExchangeExec exec = EsqlTestUtils.singleValue(physicalPlan.collect(ExchangeExec.class)); + var sink = new ExchangeSinkExec(exec.source(), exec.output(), false, exec.child()); + var reductionPlan = ComputeService.reductionPlan( EsqlTestUtils.TEST_PLANNER_SETTINGS, new EsqlFlags(false), conf, conf.newFoldContext(), - physicalPlan, - searchStats, + sink, + true, // runNodeLevelReduction + true, // reduceNodeLateMaterialization new PlanTimeProfile() + ); - result.add( - Tuple.tuple(Stage.LOCAL_PHYSICAL_OPTIMIZATION, verifyOrWrite(localPhysicalPlan, Stage.LOCAL_PHYSICAL_OPTIMIZATION)) - ); + if (stages.contains(Stage.NODE_REDUCE_OPTIMIZATION)) { + result.addAll(addDualPlanResult(Stage.NODE_REDUCE_OPTIMIZATION, reductionPlan, "node_reduce", "data")); + } + if (stages.contains(Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION)) { + var finalizedResult = new ReductionPlan( + localOptimize(reductionPlan.nodeReducePlan(), conf), + localOptimize(reductionPlan.dataNodePlan(), conf) + ); + result.addAll( + addDualPlanResult( + Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION, + finalizedResult, + "local_node_reduce", + "local_data" + ) + ); + } } } return result; } - enum TestResult { + private enum TestResult { SUCCESS, FAILURE, CREATED } + private List> addDualPlanResult( + Stage stage, + ReductionPlan plan, + String nodeReduceName, + String dataNodeName + ) throws IOException { + var reduceResult = verifyOrWrite(plan.nodeReducePlan(), outputPath("reduction_", nodeReduceName)); + var dataResult = verifyOrWrite(plan.dataNodePlan(), outputPath("reduction_", dataNodeName)); + var result = new ArrayList>(); + if (reduceResult == TestResult.FAILURE || dataResult == TestResult.FAILURE) { + result.add(Tuple.tuple(stage, TestResult.FAILURE)); + } else if (reduceResult == TestResult.CREATED || dataResult == TestResult.CREATED) { + if (reduceResult != dataResult) { + throw new IllegalStateException("Both local reduction and local data plan should be created for a new test"); + } + result.add(Tuple.tuple(stage, TestResult.CREATED)); + } else { + if (reduceResult != TestResult.SUCCESS || dataResult != TestResult.SUCCESS) { + throw new IllegalStateException("Both local reduction and local data plan should be successful at this point"); + } + result.add(Tuple.tuple(stage, TestResult.SUCCESS)); + } + return result; + } + private > TestResult verifyOrWrite(T plan, Stage stage) throws IOException { - var outputPath = outputPath(stage); + return verifyOrWrite(plan, outputPath(stage)); + } + + private > TestResult verifyOrWrite(T plan, Path outputFile) throws IOException { if (System.getProperty("golden.overwrite") != null) { - logger.info("Bulldozing file {}", outputPath); - return createNewOutput(outputPath, plan); + logger.info("Overwriting file {}", outputFile); + return createNewOutput(outputFile, plan); } else { - if (Files.exists(outputPath)) { - return verifyExisting(outputPath, plan); + if (Files.exists(outputFile)) { + return verifyExisting(outputFile, plan); } else { - logger.debug("No output exists for file {}, writing new output", outputPath); - return createNewOutput(outputPath, plan); + logger.debug("No output exists for file {}, writing new output", outputFile); + return createNewOutput(outputFile, plan); } } } private Path outputPath(Stage stage) { + return outputPath("", stage.name().toLowerCase(Locale.ROOT)); + } + + private Path outputPath(String prefix, String suffix) { var paths = new String[nestedPath.length + 2]; paths[0] = testName; System.arraycopy(nestedPath, 0, paths, 1, nestedPath.length); - paths[paths.length - 1] = Strings.format("%s.expected", stage.name().toLowerCase(Locale.ROOT)); + paths[paths.length - 1] = Strings.format("%s%s.expected", prefix, suffix); return PathUtils.get(basePath.toString(), paths); } + + private ExchangeSinkExec localOptimize(PhysicalPlan plan, Configuration conf) { + return (ExchangeSinkExec) PlannerUtils.localPlan( + EsqlTestUtils.TEST_PLANNER_SETTINGS, + new EsqlFlags(false), + conf, + conf.newFoldContext(), + plan, + searchStats, + new PlanTimeProfile() + ); + } } private static Test.TestResult createNewOutput(Path output, QueryPlan plan) throws IOException { @@ -253,9 +330,8 @@ private static String toString(Node plan) { private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("#\\d+"); private static Test.TestResult verifyExisting(Path output, QueryPlan plan) throws IOException { - String read = Files.readString(output); String testString = normalize(toString(plan)); - if (normalize(testString).equals(normalize(read))) { + if (testString.equals(normalize(Files.readString(output)))) { if (System.getProperty("golden.cleanactual") != null) { Path path = actualPath(output); if (Files.exists(path)) { @@ -292,7 +368,11 @@ protected enum Stage { PHYSICAL_OPTIMIZATION, // There's no LOCAL_LOGICAL here since in production we use PlannerUtils.localPlan to produce the local physical plan directly from // non-local physical plan. - LOCAL_PHYSICAL_OPTIMIZATION + LOCAL_PHYSICAL_OPTIMIZATION, + // Both node_reduce stages actually result in *two* plans: one for the node reduce driver and one for the data nodes. + NODE_REDUCE_OPTIMIZATION, + // Perform the local physical optimization on both node reduce and data node plans. + NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION } private static String normalize(String s) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlannerGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlannerGoldenTests.java new file mode 100644 index 0000000000000..c27e6de78f056 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlannerGoldenTests.java @@ -0,0 +1,154 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.plugin; + +import org.elasticsearch.xpack.esql.EsqlTestUtils; +import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; +import org.elasticsearch.xpack.esql.optimizer.GoldenTestCase; + +import java.util.EnumSet; + +public class LateMaterializationPlannerGoldenTests extends GoldenTestCase { + private static final EnumSet STAGES = EnumSet.of( + Stage.PHYSICAL_OPTIMIZATION, + Stage.NODE_REDUCE_OPTIMIZATION, + Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION + ); + + public void testBasicTopNLateMaterialization() throws Exception { + String query = """ + FROM employees + | keep hire_date, salary, emp_no + | SORT hire_date + | LIMIT 20 + """; + runGoldenTest(query, STAGES, unindexedStats()); + } + + public void testMultipleTopN() throws Exception { + String query = """ + FROM employees + | keep hire_date, salary, emp_no + | SORT hire_date + | LIMIT 20 + | SORT salary + | LIMIT 10 + """; + runGoldenTest(query, STAGES, unindexedStats()); + } + + public void testSomeFieldsNeededBeforeLateMaterialization() throws Exception { + String query = """ + FROM employees + | keep hire_date, salary, emp_no + | WHERE salary > 10000 + | SORT hire_date + | LIMIT 20 + """; + runGoldenTest(query, STAGES, unindexedStats()); + } + + public void testMultipleFieldSortTopN() throws Exception { + String query = """ + FROM employees + | keep hire_date, emp_no, height + | SORT hire_date, height + | LIMIT 20 + """; + runGoldenTest(query, STAGES, unindexedStats()); + } + + public void testExpressionSortTopN() throws Exception { + String query = """ + FROM employees + | keep hire_date, height + | SORT sin(height) * 2 + | LIMIT 20 + """; + runGoldenTest(query, STAGES, unindexedStats()); + } + + public void testPushedDownTopN() throws Exception { + String query = """ + FROM employees + | keep emp_no, height + | SORT height + | LIMIT 20 + """; + runGoldenTest(query, STAGES); // default stats are indexed. + } + + public void testTopNWithMissingSortField() throws Exception { + String query = """ + FROM employees + | keep hire_date, salary, emp_no + | SORT hire_date + | LIMIT 20 + """; + runGoldenTest(query, STAGES, missingFieldStats("hire_date")); + } + + public void testLookupJoinOnDataNode() throws Exception { + String query = """ + FROM employees + | EVAL language_code = languages + | LOOKUP JOIN languages_lookup ON language_code + | WHERE emp_no >= 10091 AND emp_no < 10094 + | SORT emp_no + | LIMIT 20 + """; + runGoldenTest(query, STAGES, unindexedStats()); + } + + public void testTopNThenStats() throws Exception { + String query = """ + FROM employees + | keep hire_date, salary, emp_no + | SORT hire_date + | LIMIT 20 + | STATS avg_salary = AVG(salary), count = COUNT(*) + """; + runGoldenTest(query, STAGES, unindexedStats()); + } + + public void testMvExpandBeforeTopN() throws Exception { + String query = """ + FROM employees + | keep emp_no, job_positions, salary + | MV_EXPAND job_positions + | SORT salary + | LIMIT 20 + """; + runGoldenTest(query, STAGES, unindexedStats()); + } + + // Prevents TopN pushdown. + private static EsqlTestUtils.TestSearchStats unindexedStats() { + return new EsqlTestUtils.TestSearchStats() { + @Override + public boolean isIndexed(FieldAttribute.FieldName field) { + return false; + } + }; + } + + // Returns false for exists() for the specified field, simulating a missing field on the data node. + private static EsqlTestUtils.TestSearchStats missingFieldStats(String missingField) { + return new EsqlTestUtils.TestSearchStats() { + @Override + public boolean exists(FieldAttribute.FieldName field) { + return false; + } + + @Override + public boolean isIndexed(FieldAttribute.FieldName field) { + return false; + } + }; + } +} diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected new file mode 100644 index 0000000000000..cd76be3897e14 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected @@ -0,0 +1,7 @@ +ProjectExec[[hire_date{f}, salary{f}, emp_no{f}]] +\_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}, hire_date{f}, salary{f}],false] + \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[emp_no{f}, hire_date{f}, salary{f}]] +\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_data.expected new file mode 100644 index 0000000000000..42c2f1deccb35 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_data.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}, hire_date{f}]] +\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_local_data.expected new file mode 100644 index 0000000000000..79d08e098a4ac --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_local_data.expected @@ -0,0 +1,4 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_ProjectExec[[_doc{f}, hire_date{f}]] + \_FieldExtractExec[hire_date{f}]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_local_node_reduce.expected new file mode 100644 index 0000000000000..378271a5e3f37 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_local_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] + \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> + \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_node_reduce.expected new file mode 100644 index 0000000000000..378271a5e3f37 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] + \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> + \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/physical_optimization.expected new file mode 100644 index 0000000000000..10cc006e32b1b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/physical_optimization.expected @@ -0,0 +1,8 @@ +ProjectExec[[hire_date{f}, height{f}]] +\_TopNExec[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[height{f}, hire_date{f}, $$order_by$0$0{r}],false] + \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[height{f}, hire_date{f}, $$order_by$0$0{r}]] +\_TopN[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$0]] + \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_data.expected new file mode 100644 index 0000000000000..79ce101ea8de7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_data.expected @@ -0,0 +1,6 @@ +ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by$0$0{r}],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}, height{f}, $$order_by$0$0{r}]] +\_TopN[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$0]] + \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_data.expected new file mode 100644 index 0000000000000..843bf41435308 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_data.expected @@ -0,0 +1,6 @@ +ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by$0$0{r}],false] +\_ProjectExec[[_doc{f}, height{f}, $$order_by$0$0{r}]] + \_TopNExec[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],36] + \_EvalExec[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$0]] + \_FieldExtractExec[height{f}]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_node_reduce.expected new file mode 100644 index 0000000000000..d23a70cf756e6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by$0$0{r}],false] +\_ProjectExec[[height{f}, hire_date{f}, $$order_by$0$0{r}]] + \_FieldExtractExec[hire_date{f}]<[],[]> + \_TopNExec[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],44] + \_ExchangeSourceExec[[_doc{f}, height{f}, $$order_by$0$0{r}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_node_reduce.expected new file mode 100644 index 0000000000000..d23a70cf756e6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by$0$0{r}],false] +\_ProjectExec[[height{f}, hire_date{f}, $$order_by$0$0{r}]] + \_FieldExtractExec[hire_date{f}]<[],[]> + \_TopNExec[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],44] + \_ExchangeSourceExec[[_doc{f}, height{f}, $$order_by$0$0{r}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected new file mode 100644 index 0000000000000..6de9cdeb68a29 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected @@ -0,0 +1,10 @@ +TopNExec[[Order[emp_no{f},ASC,LAST]],20[INTEGER],null] +\_ExchangeExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}],false] + \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}]] +\_TopN[[Order[emp_no{f},ASC,LAST]],20[INTEGER],false] + \_Join[LEFT,[language_code{r}],[language_code{f}],null] + |_Eval[[languages{f} AS language_code]] + | \_Filter[emp_no{f} >= 10091[INTEGER] AND emp_no{f} < 10094[INTEGER]] + | \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}, language_name{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_data.expected new file mode 100644 index 0000000000000..ef61e922e587d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_data.expected @@ -0,0 +1,9 @@ +ExchangeSinkExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}, emp_no{f}, languages{f}, language_code{r}, language_name{f}]] +\_TopN[[Order[emp_no{f},ASC,LAST]],20[INTEGER],false] + \_Join[LEFT,[language_code{r}],[language_code{f}],null] + |_Eval[[languages{f} AS language_code]] + | \_Filter[emp_no{f} >= 10091[INTEGER] AND emp_no{f} < 10094[INTEGER]] + | \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}, language_name{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_local_data.expected new file mode 100644 index 0000000000000..afa8bc120313d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_local_data.expected @@ -0,0 +1,25 @@ +ExchangeSinkExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}],false] +\_ProjectExec[[_doc{f}, emp_no{f}, languages{f}, language_code{r}, language_name{f}]] + \_TopNExec[[Order[emp_no{f},ASC,LAST]],20[INTEGER],82] + \_FieldExtractExec[emp_no{f}]<[],[]> + \_LookupJoinExec[[language_code{r}],[language_code{f}],[language_name{f}],null] + |_EvalExec[[languages{f} AS language_code]] + | \_FieldExtractExec[languages{f}]<[],[]> + | \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query={ + "esql_single_value" : { + "field" : "emp_no", + "next" : { + "range" : { + "emp_no" : { + "gte" : 10091, + "lt" : 10094, + "time_zone" : "Z", + "boost" : 0.0 + } + } + }, + "source" : "emp_no >= 10091@4:9" + } +}, tags=[]]]] + \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +EsRelation[languages_lookup][LOOKUP][language_code{f}, language_name{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_local_node_reduce.expected new file mode 100644 index 0000000000000..1c739d108e561 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_local_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}],false] +\_ProjectExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}]] + \_FieldExtractExec[avg_worked_seconds{f}, birth_date{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<[],[]> + \_TopNExec[[Order[emp_no{f},ASC,LAST]],20[INTEGER],430] + \_ExchangeSourceExec[[_doc{f}, emp_no{f}, languages{f}, language_code{r}, language_name{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_node_reduce.expected new file mode 100644 index 0000000000000..1c739d108e561 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}],false] +\_ProjectExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}]] + \_FieldExtractExec[avg_worked_seconds{f}, birth_date{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<[],[]> + \_TopNExec[[Order[emp_no{f},ASC,LAST]],20[INTEGER],430] + \_ExchangeSourceExec[[_doc{f}, emp_no{f}, languages{f}, language_code{r}, language_name{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected new file mode 100644 index 0000000000000..01e434d142dbc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected @@ -0,0 +1,7 @@ +ProjectExec[[hire_date{f}, emp_no{f}, height{f}]] +\_TopNExec[[Order[hire_date{f},ASC,LAST], Order[height{f},ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}, height{f}, hire_date{f}],false] + \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[emp_no{f}, height{f}, hire_date{f}]] +\_TopN[[Order[hire_date{f},ASC,LAST], Order[height{f},ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_data.expected new file mode 100644 index 0000000000000..8ab7e96ac70e1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_data.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, height{f}, hire_date{f}],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}, hire_date{f}, height{f}]] +\_TopN[[Order[hire_date{f},ASC,LAST], Order[height{f},ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_local_data.expected new file mode 100644 index 0000000000000..4ba472a701132 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_local_data.expected @@ -0,0 +1,4 @@ +ExchangeSinkExec[[emp_no{f}, height{f}, hire_date{f}],false] +\_ProjectExec[[_doc{f}, hire_date{f}, height{f}]] + \_FieldExtractExec[hire_date{f}, height{f}]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST], FieldSort[field=height{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[32] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_local_node_reduce.expected new file mode 100644 index 0000000000000..b4903131e7355 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_local_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, height{f}, hire_date{f}],false] +\_ProjectExec[[emp_no{f}, height{f}, hire_date{f}]] + \_FieldExtractExec[emp_no{f}]<[],[]> + \_TopNExec[[Order[hire_date{f},ASC,LAST], Order[height{f},ASC,LAST]],20[INTEGER],40] + \_ExchangeSourceExec[[_doc{f}, hire_date{f}, height{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_node_reduce.expected new file mode 100644 index 0000000000000..b4903131e7355 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, height{f}, hire_date{f}],false] +\_ProjectExec[[emp_no{f}, height{f}, hire_date{f}]] + \_FieldExtractExec[emp_no{f}]<[],[]> + \_TopNExec[[Order[hire_date{f},ASC,LAST], Order[height{f},ASC,LAST]],20[INTEGER],40] + \_ExchangeSourceExec[[_doc{f}, hire_date{f}, height{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected new file mode 100644 index 0000000000000..f614767fd6b3e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected @@ -0,0 +1,8 @@ +ProjectExec[[hire_date{f}, salary{f}, emp_no{f}]] +\_TopNExec[[Order[salary{f},ASC,LAST]],10[INTEGER],null] + \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}, hire_date{f}, salary{f}],false] + \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[emp_no{f}, hire_date{f}, salary{f}]] +\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_data.expected new file mode 100644 index 0000000000000..42c2f1deccb35 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_data.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}, hire_date{f}]] +\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_local_data.expected new file mode 100644 index 0000000000000..79d08e098a4ac --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_local_data.expected @@ -0,0 +1,4 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_ProjectExec[[_doc{f}, hire_date{f}]] + \_FieldExtractExec[hire_date{f}]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_local_node_reduce.expected new file mode 100644 index 0000000000000..378271a5e3f37 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_local_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] + \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> + \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_node_reduce.expected new file mode 100644 index 0000000000000..378271a5e3f37 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] + \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> + \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected new file mode 100644 index 0000000000000..d53c3f7c10b84 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected @@ -0,0 +1,8 @@ +TopNExec[[Order[salary{f},ASC,LAST]],20[INTEGER],null] +\_ExchangeExec[[emp_no{f}, job_positions{r}, salary{f}],false] + \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[emp_no{f}, job_positions{r}, salary{f}]] +\_TopN[[Order[salary{f},ASC,LAST]],20[INTEGER],false] + \_MvExpand[job_positions{f},job_positions{r}] + \_Project[[emp_no{f}, job_positions{f}, salary{f}]] + \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_data.expected new file mode 100644 index 0000000000000..5a4be4cccf576 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_data.expected @@ -0,0 +1,7 @@ +ExchangeSinkExec[[emp_no{f}, job_positions{r}, salary{f}],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[emp_no{f}, job_positions{r}, salary{f}]] +\_TopN[[Order[salary{f},ASC,LAST]],20[INTEGER],false] + \_MvExpand[job_positions{f},job_positions{r}] + \_Project[[emp_no{f}, job_positions{f}, salary{f}]] + \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_local_data.expected new file mode 100644 index 0000000000000..2f239d653927e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_local_data.expected @@ -0,0 +1,7 @@ +ExchangeSinkExec[[emp_no{f}, job_positions{r}, salary{f}],false] +\_ProjectExec[[emp_no{f}, job_positions{r}, salary{f}]] + \_TopNExec[[Order[salary{f},ASC,LAST]],20[INTEGER],58] + \_MvExpandExec[job_positions{f},job_positions{r}] + \_ProjectExec[[emp_no{f}, job_positions{f}, salary{f}]] + \_FieldExtractExec[emp_no{f}, job_positions{f}, salary{f}]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[62] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_local_node_reduce.expected new file mode 100644 index 0000000000000..0c801590c80b7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_local_node_reduce.expected @@ -0,0 +1,3 @@ +ExchangeSinkExec[[emp_no{f}, job_positions{r}, salary{f}],false] +\_TopNExec[[Order[salary{f},ASC,LAST]],20[INTEGER],58] + \_ExchangeSourceExec[[emp_no{f}, job_positions{r}, salary{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_node_reduce.expected new file mode 100644 index 0000000000000..0c801590c80b7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_node_reduce.expected @@ -0,0 +1,3 @@ +ExchangeSinkExec[[emp_no{f}, job_positions{r}, salary{f}],false] +\_TopNExec[[Order[salary{f},ASC,LAST]],20[INTEGER],58] + \_ExchangeSourceExec[[emp_no{f}, job_positions{r}, salary{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected new file mode 100644 index 0000000000000..896efe01a59ec --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected @@ -0,0 +1,7 @@ +ProjectExec[[emp_no{f}, height{f}]] +\_TopNExec[[Order[height{f},ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}, height{f}],false] + \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[emp_no{f}, height{f}]] +\_TopN[[Order[height{f},ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_data.expected new file mode 100644 index 0000000000000..bf2fa9c12991a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_data.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, height{f}],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}, height{f}]] +\_TopN[[Order[height{f},ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_local_data.expected new file mode 100644 index 0000000000000..b49e189701890 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_local_data.expected @@ -0,0 +1,4 @@ +ExchangeSinkExec[[emp_no{f}, height{f}],false] +\_ProjectExec[[_doc{f}, height{f}]] + \_FieldExtractExec[height{f}]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=height{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_local_node_reduce.expected new file mode 100644 index 0000000000000..787b72a5c8f72 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_local_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, height{f}],false] +\_ProjectExec[[emp_no{f}, height{f}]] + \_FieldExtractExec[emp_no{f}]<[],[]> + \_TopNExec[[Order[height{f},ASC,LAST]],20[INTEGER],32] + \_ExchangeSourceExec[[_doc{f}, height{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_node_reduce.expected new file mode 100644 index 0000000000000..787b72a5c8f72 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, height{f}],false] +\_ProjectExec[[emp_no{f}, height{f}]] + \_FieldExtractExec[emp_no{f}]<[],[]> + \_TopNExec[[Order[height{f},ASC,LAST]],20[INTEGER],32] + \_ExchangeSourceExec[[_doc{f}, height{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected new file mode 100644 index 0000000000000..f356ac8daa272 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected @@ -0,0 +1,8 @@ +ProjectExec[[hire_date{f}, salary{f}, emp_no{f}]] +\_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}, hire_date{f}, salary{f}],false] + \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[emp_no{f}, hire_date{f}, salary{f}]] +\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] + \_Filter[salary{f} > 10000[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_data.expected new file mode 100644 index 0000000000000..041b22266a09e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_data.expected @@ -0,0 +1,6 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}, salary{f}, hire_date{f}]] +\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] + \_Filter[salary{f} > 10000[INTEGER]] + \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_local_data.expected new file mode 100644 index 0000000000000..7a2b16378c969 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_local_data.expected @@ -0,0 +1,17 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_ProjectExec[[_doc{f}, salary{f}, hire_date{f}]] + \_FieldExtractExec[salary{f}, hire_date{f}]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query={ + "esql_single_value" : { + "field" : "salary", + "next" : { + "range" : { + "salary" : { + "gt" : 10000, + "boost" : 0.0 + } + } + }, + "source" : "salary > 10000@3:9" + } +}, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_local_node_reduce.expected new file mode 100644 index 0000000000000..23b988ef09a77 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_local_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] + \_FieldExtractExec[emp_no{f}]<[],[]> + \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}, salary{f}, hire_date{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_node_reduce.expected new file mode 100644 index 0000000000000..23b988ef09a77 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] + \_FieldExtractExec[emp_no{f}]<[],[]> + \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}, salary{f}, hire_date{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected new file mode 100644 index 0000000000000..861afa9e16c8f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected @@ -0,0 +1,10 @@ +ProjectExec[[avg_salary{r}, count{r}]] +\_EvalExec[[$$SUM$avg_salary$0{r$} / $$COUNT$avg_salary$1{r$} AS avg_salary]] + \_LimitExec[10000[INTEGER],null] + \_AggregateExec[[],[SUM(salary{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS $$SUM$avg_salary$0, COUNT(salary{f},true[BOOLEAN],PT0S[TIME_DURATION]) AS $$COUNT$avg_salary$1, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count],SINGLE,[$$SUM$avg_salary$0$sum{r}, $$SUM$avg_salary$0$seen{r}, $$COUNT$avg_salary$1$count{r}, $$COUNT$avg_salary$1$seen{r}, $$count$count{r}, $$count$seen{r}],null] + \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[hire_date{f}, salary{f}],false] + \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[hire_date{f}, salary{f}]] +\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_data.expected new file mode 100644 index 0000000000000..5cc08a59070fd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_data.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[hire_date{f}, salary{f}],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}, hire_date{f}]] +\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_local_data.expected new file mode 100644 index 0000000000000..6d737b8a8eb59 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_local_data.expected @@ -0,0 +1,4 @@ +ExchangeSinkExec[[hire_date{f}, salary{f}],false] +\_ProjectExec[[_doc{f}, hire_date{f}]] + \_FieldExtractExec[hire_date{f}]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_local_node_reduce.expected new file mode 100644 index 0000000000000..89b94a06e2096 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_local_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[hire_date{f}, salary{f}],false] +\_ProjectExec[[hire_date{f}, salary{f}]] + \_FieldExtractExec[salary{f}]<[],[]> + \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],32] + \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_node_reduce.expected new file mode 100644 index 0000000000000..89b94a06e2096 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[hire_date{f}, salary{f}],false] +\_ProjectExec[[hire_date{f}, salary{f}]] + \_FieldExtractExec[salary{f}]<[],[]> + \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],32] + \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected new file mode 100644 index 0000000000000..cd76be3897e14 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected @@ -0,0 +1,7 @@ +ProjectExec[[hire_date{f}, salary{f}, emp_no{f}]] +\_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}, hire_date{f}, salary{f}],false] + \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[emp_no{f}, hire_date{f}, salary{f}]] +\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_data.expected new file mode 100644 index 0000000000000..42c2f1deccb35 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_data.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}, hire_date{f}]] +\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_local_data.expected new file mode 100644 index 0000000000000..86be6bee3c591 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_local_data.expected @@ -0,0 +1,4 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_ProjectExec[[_doc{f}, birth_date{r} AS hire_date]] + \_EvalExec[[null[DATETIME] AS birth_date]] + \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_local_node_reduce.expected new file mode 100644 index 0000000000000..378271a5e3f37 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_local_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] + \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> + \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_node_reduce.expected new file mode 100644 index 0000000000000..378271a5e3f37 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_node_reduce.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] + \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> + \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file From 84976f57f2d9c404be2eb15b446eae2f08f73818 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 21 Jan 2026 23:48:05 +0200 Subject: [PATCH 002/137] Remove old test file --- ...ductionLateMaterializationGoldenTests.java | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlReductionLateMaterializationGoldenTests.java diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlReductionLateMaterializationGoldenTests.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlReductionLateMaterializationGoldenTests.java deleted file mode 100644 index 015676ebb099d..0000000000000 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlReductionLateMaterializationGoldenTests.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.esql.action; - -import org.elasticsearch.xpack.esql.optimizer.GoldenTestCase; - -import java.util.EnumSet; - -public class EsqlReductionLateMaterializationGoldenTests extends GoldenTestCase { - /* - For instance, I'd like to see the data (and reduce) plans for cases such as: - queries with more than 1 topn - queries that have mv_expand (known problem due to preventing projections from bubbling up) - queries that have lookup joins on the data node - queries that have subsequent reducers that should end up on the coordinator (e.g. topn first, then stats) - queries where some fields need to be extracted before the topn, and others don't - queries where the topn sorts on expressions and/or sorts on more than 1 field - queries where the topn can be pushed down to Lucene in the data node plan, and queries where this isn't possible. - queries where the fields required for the TopN are missing on the data node (interactions with ReplaceFieldWithConstantOrNull can be subtle and only pop up as bugs months later) - */ - - public void testMultipleTopN() throws Exception { - String query = """ - FROM employees - | SORT hire_date - | LIMIT 20 - | SORT salary - | LIMIT 10 - """; - runGoldenTest(query, EnumSet.of(Stage.NODE_REDUCE)); - } -} From 34108412c1b1277da8702a7013e638242923b485 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 22 Jan 2026 13:12:00 +0200 Subject: [PATCH 003/137] Fix failing test --- .../xpack/esql/optimizer/GoldenTestCase.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 8a3150f24e877..5595387c3ffce 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -226,8 +226,8 @@ private List> doTests() throws IOException { } if (stages.contains(Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION)) { var finalizedResult = new ReductionPlan( - localOptimize(reductionPlan.nodeReducePlan(), conf), - localOptimize(reductionPlan.dataNodePlan(), conf) + (ExchangeSinkExec) localOptimize(reductionPlan.nodeReducePlan(), conf), + (ExchangeSinkExec) localOptimize(reductionPlan.dataNodePlan(), conf) ); result.addAll( addDualPlanResult( @@ -304,8 +304,8 @@ private Path outputPath(String prefix, String suffix) { return PathUtils.get(basePath.toString(), paths); } - private ExchangeSinkExec localOptimize(PhysicalPlan plan, Configuration conf) { - return (ExchangeSinkExec) PlannerUtils.localPlan( + private PhysicalPlan localOptimize(PhysicalPlan plan, Configuration conf) { + return PlannerUtils.localPlan( EsqlTestUtils.TEST_PLANNER_SETTINGS, new EsqlFlags(false), conf, From 4066eb484f35b9de1dd136cdeb5a9054955a3005 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 22 Jan 2026 15:28:45 +0200 Subject: [PATCH 004/137] Small changes --- x-pack/plugin/esql/build.gradle | 6 +++--- .../elasticsearch/xpack/esql/optimizer/GoldenTestCase.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugin/esql/build.gradle b/x-pack/plugin/esql/build.gradle index 35346969e8f23..336b63bdbdce8 100644 --- a/x-pack/plugin/esql/build.gradle +++ b/x-pack/plugin/esql/build.gradle @@ -626,12 +626,12 @@ tasks.named("test").configure { if (System.getProperty("golden.noactual") != null || project.hasProperty("golden.noactual")) { systemProperty "golden.noactual", "true" } - if (System.getProperty("golden.overwrite") != null || project.hasProperty("golden.overwrite")) { - systemProperty "golden.overwrite", "true" - } if (System.getProperty("golden.cleanactual") != null || project.hasProperty("golden.cleanactual")) { systemProperty "golden.cleanactual", "true" } + if (System.getProperty("golden.overwrite") != null || project.hasProperty("golden.overwrite")) { + systemProperty "golden.overwrite", "true" + } systemProperty "policy.directory", file("${projectDir}").absolutePath systemProperty "java.security.policy", file("${projectDir}/test.policy").absolutePath diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 5595387c3ffce..54d0cb9183d6d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -216,8 +216,8 @@ private List> doTests() throws IOException { conf, conf.newFoldContext(), sink, - true, // runNodeLevelReduction - true, // reduceNodeLateMaterialization + true, + true, new PlanTimeProfile() ); From 5635f49649ad0b1e5a239412f379bfef5df61621 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Fri, 30 Jan 2026 14:27:59 +0200 Subject: [PATCH 005/137] CR: Add minimum random transport version --- .../xpack/esql/optimizer/GoldenTestCase.java | 50 +++++++++++++++---- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 54d0cb9183d6d..432d19182e2d2 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -61,6 +61,7 @@ import java.util.stream.Collectors; import static org.elasticsearch.xpack.esql.EsqlTestUtils.TEST_VERIFIER; +import static org.elasticsearch.xpack.esql.EsqlTestUtils.randomMinimumVersion; import static org.elasticsearch.xpack.esql.EsqlTestUtils.unboundLogicalOptimizerContext; import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.defaultLookupResolution; @@ -83,12 +84,22 @@ public GoldenTestCase() { } protected void runGoldenTest(String esqlQuery, EnumSet stages, String... nestedPath) { - runGoldenTest(esqlQuery, stages, EsqlTestUtils.TEST_SEARCH_STATS, nestedPath); + builder(esqlQuery).stages(stages).nestedPath(nestedPath).run(); } protected void runGoldenTest(String esqlQuery, EnumSet stages, SearchStats searchStats, String... nestedPath) { + builder(esqlQuery).stages(stages).searchStats(searchStats).nestedPath(nestedPath).run(); + } + + protected void runGoldenTest( + String esqlQuery, + EnumSet stages, + SearchStats searchStats, + TransportVersion transportVersion, + String... nestedPath + ) { String testName = extractTestName(); - new Test(baseFile, testName, nestedPath, esqlQuery, stages, searchStats).doTest(); + new Test(baseFile, testName, nestedPath, esqlQuery, stages, searchStats, transportVersion).doTest(); } protected TestBuilder builder(String esqlQuery) { @@ -100,16 +111,24 @@ protected final class TestBuilder { private EnumSet stages; private SearchStats searchStats; private String[] nestedPath; - - private TestBuilder(String esqlQuery, EnumSet stages, SearchStats searchStats, String[] nestedPath) { + private TransportVersion transportVersion; + + private TestBuilder( + String esqlQuery, + EnumSet stages, + SearchStats searchStats, + String[] nestedPath, + TransportVersion transportVersion + ) { this.esqlQuery = esqlQuery; this.stages = stages; this.searchStats = searchStats; this.nestedPath = nestedPath; + this.transportVersion = transportVersion; } TestBuilder(String esqlQuery) { - this(esqlQuery, EnumSet.allOf(Stage.class), EsqlTestUtils.TEST_SEARCH_STATS, new String[0]); + this(esqlQuery, EnumSet.allOf(Stage.class), EsqlTestUtils.TEST_SEARCH_STATS, new String[0], randomMinimumVersion()); } public TestBuilder stages(EnumSet stages) { @@ -139,8 +158,17 @@ public String[] nestedPath() { return nestedPath; } + public TransportVersion transportVersion() { + return transportVersion; + } + + public TestBuilder transportVersion(TransportVersion transportVersion) { + this.transportVersion = transportVersion; + return this; + } + public void run() { - runGoldenTest(esqlQuery, stages, searchStats, nestedPath); + runGoldenTest(esqlQuery, stages, searchStats, transportVersion, nestedPath); } } @@ -150,7 +178,8 @@ private record Test( String[] nestedPath, String esqlQuery, EnumSet stages, - SearchStats searchStats + SearchStats searchStats, + TransportVersion transportVersion ) { private void doTest() { @@ -167,7 +196,6 @@ private void doTest() { private List> doTests() throws IOException { LogicalPlan parsedStatement = EsqlParser.INSTANCE.parseQuery(esqlQuery); - TransportVersion version = TransportVersion.current(); var analyzer = new Analyzer( new AnalyzerContext( EsqlTestUtils.TEST_CFG, @@ -176,7 +204,7 @@ private List> doTests() throws IOException { defaultLookupResolution(), new EnrichResolution(), InferenceResolution.EMPTY, - version, + transportVersion, UnmappedResolution.FAIL ), TEST_VERIFIER @@ -198,7 +226,9 @@ private List> doTests() throws IOException { || stages.contains(Stage.NODE_REDUCE_OPTIMIZATION) || stages.contains(Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION)) { var physicalPlanOptimizer = new PhysicalPlanOptimizer(new PhysicalOptimizerContext(null, null)); - PhysicalPlan physicalPlan = physicalPlanOptimizer.optimize(new Mapper().map(new Versioned<>(logicallyOptimized, version))); + PhysicalPlan physicalPlan = physicalPlanOptimizer.optimize( + new Mapper().map(new Versioned<>(logicallyOptimized, transportVersion)) + ); if (stages.contains(Stage.PHYSICAL_OPTIMIZATION)) { result.add(Tuple.tuple(Stage.PHYSICAL_OPTIMIZATION, verifyOrWrite(physicalPlan, Stage.PHYSICAL_OPTIMIZATION))); } From 84a15de949c769878c3a2911bacd4ad5b68177e9 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Fri, 30 Jan 2026 16:50:11 +0200 Subject: [PATCH 006/137] CR: Add ESQL query to the output --- .../xpack/esql/optimizer/GoldenTestCase.java | 29 ++++++++++++++----- .../query.esql | 4 +++ .../query.esql | 4 +++ .../query.esql | 2 ++ .../query.esql | 2 ++ .../query.esql | 2 ++ .../query.esql | 3 ++ .../query.esql | 2 ++ .../query.esql | 5 ++++ .../query.esql | 3 ++ .../query.esql | 2 ++ .../query.esql | 2 ++ .../query.esql | 4 +++ .../testExpressionSortTopN/query.esql | 4 +++ .../testLookupJoinOnDataNode/query.esql | 6 ++++ .../testMultipleFieldSortTopN/query.esql | 4 +++ .../testMultipleTopN/query.esql | 6 ++++ .../testMvExpandBeforeTopN/query.esql | 5 ++++ .../testPushedDownTopN/query.esql | 4 +++ .../query.esql | 5 ++++ .../testTopNThenStats/query.esql | 5 ++++ .../testTopNWithMissingSortField/query.esql | 4 +++ 22 files changed, 100 insertions(+), 7 deletions(-) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/query.esql diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 432d19182e2d2..23bb65195c55f 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -25,6 +25,7 @@ import org.elasticsearch.xpack.esql.analysis.AnalyzerContext; import org.elasticsearch.xpack.esql.analysis.EnrichResolution; import org.elasticsearch.xpack.esql.analysis.UnmappedResolution; +import org.elasticsearch.xpack.esql.core.expression.FoldContext; import org.elasticsearch.xpack.esql.core.tree.Node; import org.elasticsearch.xpack.esql.expression.function.EsqlFunctionRegistry; import org.elasticsearch.xpack.esql.inference.InferenceResolution; @@ -62,7 +63,6 @@ import static org.elasticsearch.xpack.esql.EsqlTestUtils.TEST_VERIFIER; import static org.elasticsearch.xpack.esql.EsqlTestUtils.randomMinimumVersion; -import static org.elasticsearch.xpack.esql.EsqlTestUtils.unboundLogicalOptimizerContext; import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.defaultLookupResolution; @@ -196,6 +196,7 @@ private void doTest() { private List> doTests() throws IOException { LogicalPlan parsedStatement = EsqlParser.INSTANCE.parseQuery(esqlQuery); + Files.writeString(PathUtils.get(basePath.toString(), testName, "query.esql"), esqlQuery); var analyzer = new Analyzer( new AnalyzerContext( EsqlTestUtils.TEST_CFG, @@ -217,7 +218,8 @@ private List> doTests() throws IOException { if (stages.equals(EnumSet.of(Stage.ANALYSIS))) { return result; } - var logicallyOptimized = new LogicalPlanOptimizer(unboundLogicalOptimizerContext()).optimize(analyzed); + var optimizerContext = new LogicalOptimizerContext(EsqlTestUtils.TEST_CFG, FoldContext.small(), transportVersion); + var logicallyOptimized = new LogicalPlanOptimizer(optimizerContext).optimize(analyzed); if (stages.contains(Stage.LOGICAL_OPTIMIZATION)) { result.add(Tuple.tuple(Stage.LOGICAL_OPTIMIZATION, verifyOrWrite(logicallyOptimized, Stage.LOGICAL_OPTIMIZATION))); } @@ -225,7 +227,9 @@ private List> doTests() throws IOException { || stages.contains(Stage.LOCAL_PHYSICAL_OPTIMIZATION) || stages.contains(Stage.NODE_REDUCE_OPTIMIZATION) || stages.contains(Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION)) { - var physicalPlanOptimizer = new PhysicalPlanOptimizer(new PhysicalOptimizerContext(null, null)); + var physicalPlanOptimizer = new PhysicalPlanOptimizer( + new PhysicalOptimizerContext(EsqlTestUtils.TEST_CFG, transportVersion) + ); PhysicalPlan physicalPlan = physicalPlanOptimizer.optimize( new Mapper().map(new Versioned<>(logicallyOptimized, transportVersion)) ); @@ -393,15 +397,26 @@ protected List filteredWarnings() { } protected enum Stage { + /** See {@link Analyzer}. */ ANALYSIS, + /** See {@link LogicalPlanOptimizer}. */ LOGICAL_OPTIMIZATION, + /** See {@link PhysicalPlanOptimizer}. */ PHYSICAL_OPTIMIZATION, - // There's no LOCAL_LOGICAL here since in production we use PlannerUtils.localPlan to produce the local physical plan directly from - // non-local physical plan. + /** + * See {@link LocalPhysicalPlanOptimizer}. There's no LOCAL_LOGICAL here since in production we use PlannerUtils.localPlan to + * produce the local physical plan directly from non-local physical plan. + */ LOCAL_PHYSICAL_OPTIMIZATION, - // Both node_reduce stages actually result in *two* plans: one for the node reduce driver and one for the data nodes. + /** + * See {@link ComputeService#reductionPlan}. Actually results in two plans: one for the node reduce driver and one for the + * data nodes. + */ NODE_REDUCE_OPTIMIZATION, - // Perform the local physical optimization on both node reduce and data node plans. + /** + * A combination of {@link Stage#NODE_REDUCE_OPTIMIZATION} and {@link Stage#LOCAL_PHYSICAL_OPTIMIZATION}: first produce the node + * reduce and data node plans, and then perform local physical optimization on both. + */ NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION } diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/query.esql new file mode 100644 index 0000000000000..c8f08b2e6dd38 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/query.esql @@ -0,0 +1,4 @@ +from all_types +| fork (where integer > 100) +(where keyword : "keyword") +| stats count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/query.esql new file mode 100644 index 0000000000000..7472b3a4d943e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/query.esql @@ -0,0 +1,4 @@ +from all_types +| rename integer as language_code +| lookup join languages_lookup on language_code +| stats count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/query.esql new file mode 100644 index 0000000000000..46e5cd746c53f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/query.esql new file mode 100644 index 0000000000000..46e5cd746c53f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/query.esql new file mode 100644 index 0000000000000..48b94551ef462 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats sum(long), count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/query.esql new file mode 100644 index 0000000000000..d252b63236f6b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/query.esql @@ -0,0 +1,3 @@ +from all_types +| where keyword : "keyword" +| stats count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/query.esql new file mode 100644 index 0000000000000..33092020e833b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) where long > 10 by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/query.esql new file mode 100644 index 0000000000000..327c15df1eb1c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/query.esql @@ -0,0 +1,5 @@ +from all_types +| sort date +| eval x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") +| keep alias_integer, date, x +| limit 5 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/query.esql new file mode 100644 index 0000000000000..72b45c8bf9ea4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/query.esql @@ -0,0 +1,3 @@ +from all_types +| fork (stats x = count(*), y = max(long) by hd = date_trunc(1 day, date)) +(stats x = count(*), y = min(long) by hd = date_trunc(2 day, date)) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/query.esql new file mode 100644 index 0000000000000..2af1315b103ac --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(long, 1697760000000,1697846400000,1697932800000,1698019200000) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/query.esql new file mode 100644 index 0000000000000..948940292181b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/query.esql @@ -0,0 +1,2 @@ +from all_types, (from all_types | stats cnt = count(*) by x = date_trunc(1 day, date)) +| keep x, cnt, date diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/query.esql new file mode 100644 index 0000000000000..8d87154eaac5d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/query.esql @@ -0,0 +1,4 @@ +FROM employees +| keep hire_date, salary, emp_no +| SORT hire_date +| LIMIT 20 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/query.esql new file mode 100644 index 0000000000000..fca907a58b931 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/query.esql @@ -0,0 +1,4 @@ +FROM employees +| keep hire_date, height +| SORT sin(height) * 2 +| LIMIT 20 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/query.esql new file mode 100644 index 0000000000000..39ae29f7957c7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/query.esql @@ -0,0 +1,6 @@ +FROM employees +| EVAL language_code = languages +| LOOKUP JOIN languages_lookup ON language_code +| WHERE emp_no >= 10091 AND emp_no < 10094 +| SORT emp_no +| LIMIT 20 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/query.esql new file mode 100644 index 0000000000000..f1fb24257897e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/query.esql @@ -0,0 +1,4 @@ +FROM employees +| keep hire_date, emp_no, height +| SORT hire_date, height +| LIMIT 20 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/query.esql new file mode 100644 index 0000000000000..99a7a471aeed3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/query.esql @@ -0,0 +1,6 @@ +FROM employees +| keep hire_date, salary, emp_no +| SORT hire_date +| LIMIT 20 +| SORT salary +| LIMIT 10 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/query.esql new file mode 100644 index 0000000000000..4420e13bc89f7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/query.esql @@ -0,0 +1,5 @@ +FROM employees +| keep emp_no, job_positions, salary +| MV_EXPAND job_positions +| SORT salary +| LIMIT 20 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/query.esql new file mode 100644 index 0000000000000..d9d69d124a61b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/query.esql @@ -0,0 +1,4 @@ +FROM employees +| keep emp_no, height +| SORT height +| LIMIT 20 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/query.esql new file mode 100644 index 0000000000000..cb231bdf6f2dd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/query.esql @@ -0,0 +1,5 @@ +FROM employees +| keep hire_date, salary, emp_no +| WHERE salary > 10000 +| SORT hire_date +| LIMIT 20 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/query.esql new file mode 100644 index 0000000000000..f80ab35edf35a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/query.esql @@ -0,0 +1,5 @@ +FROM employees +| keep hire_date, salary, emp_no +| SORT hire_date +| LIMIT 20 +| STATS avg_salary = AVG(salary), count = COUNT(*) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/query.esql new file mode 100644 index 0000000000000..8d87154eaac5d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/query.esql @@ -0,0 +1,4 @@ +FROM employees +| keep hire_date, salary, emp_no +| SORT hire_date +| LIMIT 20 From 06d4661776e91caa00e77c18963c38bb82e4cd35 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Fri, 30 Jan 2026 22:25:37 +0200 Subject: [PATCH 007/137] Remove local node reduction tests in some cases --- .../xpack/esql/planner/PlannerUtils.java | 2 + .../esql/plugin/ClusterComputeHandler.java | 1 + .../xpack/esql/plugin/ComputeService.java | 57 ++++++++++++++----- .../esql/plugin/DataNodeComputeHandler.java | 13 ++++- .../plugin/LateMaterializationPlanner.java | 2 +- .../NodeReduceLocalPhysicalOptimization.java | 14 +++++ .../xpack/esql/plugin/ReductionPlan.java | 10 +++- .../xpack/esql/optimizer/GoldenTestCase.java | 38 ++++++++----- .../reduction_local_node_reduce.expected | 5 -- .../reduction_local_node_reduce.expected | 5 -- .../reduction_local_node_reduce.expected | 5 -- .../reduction_local_node_reduce.expected | 5 -- .../reduction_local_node_reduce.expected | 5 -- .../reduction_local_node_reduce.expected | 5 -- .../reduction_local_node_reduce.expected | 5 -- .../reduction_local_node_reduce.expected | 5 -- .../reduction_local_node_reduce.expected | 5 -- 17 files changed, 106 insertions(+), 76 deletions(-) create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/NodeReduceLocalPhysicalOptimization.java delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_local_node_reduce.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_node_reduce.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_local_node_reduce.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_local_node_reduce.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_local_node_reduce.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_local_node_reduce.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_local_node_reduce.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_local_node_reduce.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_local_node_reduce.expected diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java index 2755625502a7c..09c0f51857f0f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java @@ -262,6 +262,8 @@ public static PhysicalPlan localPlan( return EstimatesRowSize.estimateRowSize(f.estimatedRowSize(), localOptimized); }); + // TODO add a test assertion for the consistency checker (see + // https://github.com/elastic/elasticsearch/pull/141082/changes#r2745334028); PhysicalPlan resultPlan = isCoordPlan.get() ? plan : localPhysicalPlan; return resultPlan; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ClusterComputeHandler.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ClusterComputeHandler.java index 6abdf64654a7c..07c82f9efb71d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ClusterComputeHandler.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ClusterComputeHandler.java @@ -303,6 +303,7 @@ void runComputeOnRemoteCluster( () -> exchangeSink.createExchangeSink(() -> {}) ), coordinatorPlan, + NodeReduceLocalPhysicalOptimization.ENABLED, configuration.profile() ? new PlanTimeProfile() : null, computeListener.acquireCompute() ); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeService.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeService.java index 6684fdf55b37b..768e3663e6776 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeService.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeService.java @@ -206,7 +206,7 @@ public void execute( ActionListener listener ) { assert ThreadPool.assertCurrentThreadPool( - EsqlPlugin.ESQL_WORKER_THREAD_POOL_NAME, + ESQL_WORKER_THREAD_POOL_NAME, ThreadPool.Names.SYSTEM_READ, ThreadPool.Names.SEARCH, ThreadPool.Names.SEARCH_COORDINATION @@ -284,7 +284,14 @@ public void execute( }) ) ) { - runCompute(rootTask, computeContext, mainPlan, planTimeProfile, localListener.acquireCompute()); + runCompute( + rootTask, + computeContext, + mainPlan, + NodeReduceLocalPhysicalOptimization.ENABLED, + planTimeProfile, + localListener.acquireCompute() + ); for (int i = 0; i < subplans.size(); i++) { var subplan = subplans.get(i); @@ -387,7 +394,14 @@ public void executePlan( }) ) ) { - runCompute(rootTask, computeContext, coordinatorPlan, planTimeProfile, computeListener.acquireCompute()); + runCompute( + rootTask, + computeContext, + coordinatorPlan, + NodeReduceLocalPhysicalOptimization.ENABLED, + planTimeProfile, + computeListener.acquireCompute() + ); return; } } else { @@ -468,6 +482,7 @@ public void executePlan( exchangeSinkSupplier ), coordinatorPlan, + NodeReduceLocalPhysicalOptimization.ENABLED, planTimeProfile, localListener.acquireCompute() ); @@ -642,6 +657,7 @@ void runCompute( CancellableTask task, ComputeContext context, PhysicalPlan plan, + NodeReduceLocalPhysicalOptimization nodeReduceLocalPhysicalOptimization, PlanTimeProfile planTimeProfile, ActionListener listener ) { @@ -674,15 +690,18 @@ void runCompute( List localContexts = new ArrayList<>(); context.searchExecutionContexts().iterable().forEach(localContexts::add); - var localPlan = PlannerUtils.localPlan( - plannerSettings, - context.flags(), - localContexts, - context.configuration(), - context.foldCtx(), - plan, - planTimeProfile - ); + var localPlan = switch (nodeReduceLocalPhysicalOptimization) { + case ENABLED -> PlannerUtils.localPlan( + plannerSettings, + context.flags(), + localContexts, + context.configuration(), + context.foldCtx(), + plan, + planTimeProfile + ); + case DISABLED -> plan; + }; if (LOGGER.isDebugEnabled()) { LOGGER.debug("Local plan for {}:\n{}", context.description(), localPlan); } @@ -771,14 +790,19 @@ public static ReductionPlan reductionPlan( ) { long startTime = planTimeProfile == null ? 0 : System.nanoTime(); PhysicalPlan source = new ExchangeSourceExec(originalPlan.source(), originalPlan.output(), originalPlan.isIntermediateAgg()); - ReductionPlan defaultResult = new ReductionPlan(originalPlan.replaceChild(source), originalPlan); + ReductionPlan defaultResult = new ReductionPlan( + originalPlan.replaceChild(source), + originalPlan, + NodeReduceLocalPhysicalOptimization.ENABLED + ); if (reduceNodeLateMaterialization == false && runNodeLevelReduction == false) { return defaultResult; } Function placePlanBetweenExchanges = p -> new ReductionPlan( originalPlan.replaceChild(p.replaceChildren(List.of(source))), - originalPlan + originalPlan, + NodeReduceLocalPhysicalOptimization.ENABLED ); // The default plan is just the exchange source piped directly into the exchange sink. ReductionPlan reductionPlan = switch (PlannerUtils.reductionPlan(originalPlan)) { @@ -792,7 +816,10 @@ public static ReductionPlan reductionPlan( ) // Fallback to the behavior listed below, i.e., a regular top n reduction without loading new fields. .orElseGet(() -> runNodeLevelReduction ? placePlanBetweenExchanges.apply(topN.plan()) : defaultResult); - case PlannerUtils.TopNReduction topN when runNodeLevelReduction -> placePlanBetweenExchanges.apply(topN.plan()); + case PlannerUtils.TopNReduction topN when runNodeLevelReduction -> + // The TopN reduction plan should not be further optimized locally on the node reduce driver, since we took great pains to + // preplan in advance, including all the necessary field extractions! + placePlanBetweenExchanges.apply(topN.plan()).withoutNodeReduceLocalPhysicalOptimization(); case PlannerUtils.ReducedPlan rp when runNodeLevelReduction -> placePlanBetweenExchanges.apply(rp.plan()); default -> defaultResult; }; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeComputeHandler.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeComputeHandler.java index 5e17b436e03a0..a63a8cbcf6b46 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeComputeHandler.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeComputeHandler.java @@ -350,6 +350,7 @@ public void onFailure(Exception e) { parentTask, computeContext, request.plan(), + NodeReduceLocalPhysicalOptimization.ENABLED, planTimeProfile, sub.acquireCompute() ); @@ -367,7 +368,14 @@ public void onFailure(Exception e) { null, () -> exchangeSink.createExchangeSink(pagesProduced::incrementAndGet) ); - computeService.runCompute(parentTask, computeContext, request.plan(), planTimeProfile, batchListener); + computeService.runCompute( + parentTask, + computeContext, + request.plan(), + NodeReduceLocalPhysicalOptimization.ENABLED, + planTimeProfile, + batchListener + ); } }, batchListener::onFailure) ); @@ -471,6 +479,7 @@ private void runComputeOnDataNode( CancellableTask task, String externalId, PhysicalPlan reducePlan, + NodeReduceLocalPhysicalOptimization nodeReduceLocalPhysicalOptimization, DataNodeRequest request, boolean failFastOnShardFailure, AcquiredSearchContexts searchContexts, @@ -532,6 +541,7 @@ private void runComputeOnDataNode( () -> externalSink.createExchangeSink(() -> {}) ), reducePlan, + nodeReduceLocalPhysicalOptimization, planTimeProfile, ActionListener.wrap(resp -> { // don't return until all pages are fetched @@ -600,6 +610,7 @@ public void messageReceived(DataNodeRequest request, TransportChannel channel, T (CancellableTask) task, sessionId, reductionPlan.nodeReducePlan(), + reductionPlan.nodeReduceLocalPhysicalOptimization(), request.withPlan(reductionPlan.dataNodePlan()), failFastOnShardFailures, computeSearchContexts, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlanner.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlanner.java index 793e3846a1734..678d3a7540242 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlanner.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlanner.java @@ -139,7 +139,7 @@ public static Optional planReduceDriverTopN( EstimatesRowSize.estimateRowSize(updatedFragmentExec.estimatedRowSize(), reductionPlan) ); - return Optional.of(new ReductionPlan(reductionPlanWithSize, updatedDataPlan)); + return Optional.of(new ReductionPlan(reductionPlanWithSize, updatedDataPlan, NodeReduceLocalPhysicalOptimization.DISABLED)); } private static PhysicalPlan toPhysical(LogicalPlan plan, LocalPhysicalOptimizerContext context) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/NodeReduceLocalPhysicalOptimization.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/NodeReduceLocalPhysicalOptimization.java new file mode 100644 index 0000000000000..449befb396cdc --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/NodeReduceLocalPhysicalOptimization.java @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.plugin; + +/** This class is {@code public} for testing. */ +public enum NodeReduceLocalPhysicalOptimization { + ENABLED, + DISABLED +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ReductionPlan.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ReductionPlan.java index 9e7ee12aa3e03..83a0e27808586 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ReductionPlan.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ReductionPlan.java @@ -17,4 +17,12 @@ * @param dataNodePlan The plan to be executed on the data driver. This may contain a * {@link org.elasticsearch.xpack.esql.plan.physical.FragmentExec}. */ -public record ReductionPlan(ExchangeSinkExec nodeReducePlan, ExchangeSinkExec dataNodePlan) {} +public record ReductionPlan( + ExchangeSinkExec nodeReducePlan, + ExchangeSinkExec dataNodePlan, + NodeReduceLocalPhysicalOptimization nodeReduceLocalPhysicalOptimization +) { + public ReductionPlan withoutNodeReduceLocalPhysicalOptimization() { + return new ReductionPlan(nodeReducePlan, dataNodePlan, NodeReduceLocalPhysicalOptimization.DISABLED); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 23bb65195c55f..86b2be3329d1a 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -196,6 +196,7 @@ private void doTest() { private List> doTests() throws IOException { LogicalPlan parsedStatement = EsqlParser.INSTANCE.parseQuery(esqlQuery); + Files.createDirectories(PathUtils.get(basePath.toString(), testName)); Files.writeString(PathUtils.get(basePath.toString(), testName, "query.esql"), esqlQuery); var analyzer = new Analyzer( new AnalyzerContext( @@ -258,19 +259,31 @@ private List> doTests() throws IOException { if (stages.contains(Stage.NODE_REDUCE_OPTIMIZATION)) { result.addAll(addDualPlanResult(Stage.NODE_REDUCE_OPTIMIZATION, reductionPlan, "node_reduce", "data")); } + // FIXME(gal, NOCOMMIT) Simplify this, this shouldn't only perform the local optimization on the data plan. if (stages.contains(Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION)) { - var finalizedResult = new ReductionPlan( - (ExchangeSinkExec) localOptimize(reductionPlan.nodeReducePlan(), conf), - (ExchangeSinkExec) localOptimize(reductionPlan.dataNodePlan(), conf) - ); - result.addAll( - addDualPlanResult( - Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION, - finalizedResult, - "local_node_reduce", - "local_data" - ) - ); + switch (reductionPlan.nodeReduceLocalPhysicalOptimization()) { + // FIXME(gal, NOCOMMIT) document + case DISABLED -> { + var foo = localOptimize(reductionPlan.dataNodePlan(), conf); + var bar = verifyOrWrite(foo, outputPath("reduction_", "local_data")); + result.add(Tuple.tuple(Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION, bar)); + } + case ENABLED -> { + var finalizedResult = new ReductionPlan( + (ExchangeSinkExec) localOptimize(reductionPlan.nodeReducePlan(), conf), + (ExchangeSinkExec) localOptimize(reductionPlan.dataNodePlan(), conf), + reductionPlan.nodeReduceLocalPhysicalOptimization() + ); + result.addAll( + addDualPlanResult( + Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION, + finalizedResult, + "local_node_reduce", + "local_data" + ) + ); + } + } } } } @@ -352,7 +365,6 @@ private PhysicalPlan localOptimize(PhysicalPlan plan, Configuration conf) { } private static Test.TestResult createNewOutput(Path output, QueryPlan plan) throws IOException { - Files.createDirectories(output.getParent()); Files.writeString(output, toString(plan), StandardCharsets.UTF_8); return Test.TestResult.CREATED; } diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_local_node_reduce.expected deleted file mode 100644 index 378271a5e3f37..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_local_node_reduce.expected +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] - \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_node_reduce.expected deleted file mode 100644 index d23a70cf756e6..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_node_reduce.expected +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by$0$0{r}],false] -\_ProjectExec[[height{f}, hire_date{f}, $$order_by$0$0{r}]] - \_FieldExtractExec[hire_date{f}]<[],[]> - \_TopNExec[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],44] - \_ExchangeSourceExec[[_doc{f}, height{f}, $$order_by$0$0{r}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_local_node_reduce.expected deleted file mode 100644 index 1c739d108e561..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_local_node_reduce.expected +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}],false] -\_ProjectExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}]] - \_FieldExtractExec[avg_worked_seconds{f}, birth_date{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<[],[]> - \_TopNExec[[Order[emp_no{f},ASC,LAST]],20[INTEGER],430] - \_ExchangeSourceExec[[_doc{f}, emp_no{f}, languages{f}, language_code{r}, language_name{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_local_node_reduce.expected deleted file mode 100644 index b4903131e7355..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_local_node_reduce.expected +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}, height{f}, hire_date{f}],false] -\_ProjectExec[[emp_no{f}, height{f}, hire_date{f}]] - \_FieldExtractExec[emp_no{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST], Order[height{f},ASC,LAST]],20[INTEGER],40] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}, height{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_local_node_reduce.expected deleted file mode 100644 index 378271a5e3f37..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_local_node_reduce.expected +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] - \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_local_node_reduce.expected deleted file mode 100644 index 787b72a5c8f72..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_local_node_reduce.expected +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}, height{f}],false] -\_ProjectExec[[emp_no{f}, height{f}]] - \_FieldExtractExec[emp_no{f}]<[],[]> - \_TopNExec[[Order[height{f},ASC,LAST]],20[INTEGER],32] - \_ExchangeSourceExec[[_doc{f}, height{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_local_node_reduce.expected deleted file mode 100644 index 23b988ef09a77..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_local_node_reduce.expected +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] - \_FieldExtractExec[emp_no{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, salary{f}, hire_date{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_local_node_reduce.expected deleted file mode 100644 index 89b94a06e2096..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_local_node_reduce.expected +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[hire_date{f}, salary{f}],false] -\_ProjectExec[[hire_date{f}, salary{f}]] - \_FieldExtractExec[salary{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],32] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_local_node_reduce.expected deleted file mode 100644 index 378271a5e3f37..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_local_node_reduce.expected +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] - \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file From f82a95a373915b7b8222f1aef8c5108d23f78b91 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 2 Feb 2026 20:24:21 +0200 Subject: [PATCH 008/137] More CR Fixes --- .../plugin/LateMaterializationPlanner.java | 1 + .../xpack/esql/optimizer/GoldenTestCase.java | 76 +++++++++++++------ ...LateMaterializationPlannerGoldenTests.java | 14 +++- ...hysical_optimization_data_driver.expected} | 0 ...local_reduce_planned_data_driver.expected} | 0 ...cal_reduce_planned_reduce_driver.expected} | 0 .../reduction_node_reduce.expected | 5 -- ...hysical_optimization_data_driver.expected} | 4 +- ...local_reduce_planned_data_driver.expected} | 4 +- ...ocal_reduce_planned_reduce_driver.expected | 5 ++ .../physical_optimization.expected | 6 +- .../query.esql | 4 + ...physical_optimization_data_driver.expected | 6 ++ .../local_reduce_planned_data_driver.expected | 6 ++ ...ocal_reduce_planned_reduce_driver.expected | 5 ++ .../physical_optimization.expected | 8 ++ .../query.esql | 0 ...hysical_optimization_data_driver.expected} | 0 ...local_reduce_planned_data_driver.expected} | 0 ...cal_reduce_planned_reduce_driver.expected} | 0 ...hysical_optimization_data_driver.expected} | 0 ...local_reduce_planned_data_driver.expected} | 0 ...cal_reduce_planned_reduce_driver.expected} | 0 ...hysical_optimization_data_driver.expected} | 0 ...local_reduce_planned_data_driver.expected} | 0 ...cal_reduce_planned_reduce_driver.expected} | 0 ...hysical_optimization_data_driver.expected} | 0 ...sical_optimization_reduce_driver.expected} | 0 ...local_reduce_planned_data_driver.expected} | 0 ...cal_reduce_planned_reduce_driver.expected} | 0 ...hysical_optimization_data_driver.expected} | 0 ...local_reduce_planned_data_driver.expected} | 0 ...cal_reduce_planned_reduce_driver.expected} | 0 ...hysical_optimization_data_driver.expected} | 0 ...local_reduce_planned_data_driver.expected} | 0 ...cal_reduce_planned_reduce_driver.expected} | 0 ...hysical_optimization_data_driver.expected} | 0 ...local_reduce_planned_data_driver.expected} | 0 ...cal_reduce_planned_reduce_driver.expected} | 0 ...hysical_optimization_data_driver.expected} | 0 ...local_reduce_planned_data_driver.expected} | 0 ...cal_reduce_planned_reduce_driver.expected} | 0 42 files changed, 108 insertions(+), 36 deletions(-) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/{reduction_local_data.expected => local_reduce_physical_optimization_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/{reduction_data.expected => local_reduce_planned_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/{reduction_node_reduce.expected => local_reduce_planned_reduce_driver.expected} (100%) delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_node_reduce.expected rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/{testExpressionSortTopN/reduction_local_data.expected => testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected} (73%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/{testExpressionSortTopN/reduction_data.expected => testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected} (84%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/{testExpressionSortTopN => testExpressionSortTopNKeepAfterSort}/physical_optimization.expected (81%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/{testExpressionSortTopN => testExpressionSortTopNKeepBeforeSort}/query.esql (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/{reduction_local_data.expected => local_reduce_physical_optimization_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/{reduction_data.expected => local_reduce_planned_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/{reduction_node_reduce.expected => local_reduce_planned_reduce_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/{reduction_local_data.expected => local_reduce_physical_optimization_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/{reduction_data.expected => local_reduce_planned_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/{reduction_node_reduce.expected => local_reduce_planned_reduce_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/{reduction_local_data.expected => local_reduce_physical_optimization_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/{reduction_data.expected => local_reduce_planned_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/{reduction_node_reduce.expected => local_reduce_planned_reduce_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/{reduction_local_data.expected => local_reduce_physical_optimization_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/{reduction_local_node_reduce.expected => local_reduce_physical_optimization_reduce_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/{reduction_data.expected => local_reduce_planned_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/{reduction_node_reduce.expected => local_reduce_planned_reduce_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/{reduction_local_data.expected => local_reduce_physical_optimization_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/{reduction_data.expected => local_reduce_planned_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/{reduction_node_reduce.expected => local_reduce_planned_reduce_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/{reduction_local_data.expected => local_reduce_physical_optimization_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/{reduction_data.expected => local_reduce_planned_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/{reduction_node_reduce.expected => local_reduce_planned_reduce_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/{reduction_local_data.expected => local_reduce_physical_optimization_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/{reduction_data.expected => local_reduce_planned_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/{reduction_node_reduce.expected => local_reduce_planned_reduce_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/{reduction_local_data.expected => local_reduce_physical_optimization_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/{reduction_data.expected => local_reduce_planned_data_driver.expected} (100%) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/{reduction_node_reduce.expected => local_reduce_planned_reduce_driver.expected} (100%) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlanner.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlanner.java index 678d3a7540242..6660fa9e4d843 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlanner.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlanner.java @@ -128,6 +128,7 @@ public static Optional planReduceDriverTopN( } var updatedFragment = new Project(Source.EMPTY, withAddedDocToRelation, expectedDataOutput); FragmentExec updatedFragmentExec = fragmentExec.withFragment(updatedFragment); + // TODO This ignores the possible change in output, see #141654 ExchangeSinkExec updatedDataPlan = originalPlan.replaceChild(updatedFragmentExec); // Replace the TopN child with the data driver as the source. diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 86b2be3329d1a..4976d5e1db864 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -9,6 +9,7 @@ import com.carrotsearch.randomizedtesting.annotations.Listeners; +import org.apache.lucene.tests.util.LuceneTestCase; import org.elasticsearch.TransportVersion; import org.elasticsearch.common.Strings; import org.elasticsearch.compute.operator.PlanTimeProfile; @@ -57,7 +58,6 @@ import java.util.ArrayList; import java.util.EnumSet; import java.util.List; -import java.util.Locale; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -68,6 +68,7 @@ /** See GoldenTestsReadme.md for more information about these tests. */ @Listeners({ GoldenTestCase.GoldenTestReproduceInfoPrinter.class }) +@LuceneTestCase.SuppressFileSystems("ExtrasFS") // ExtraFS can create extraneous files in the output directory. public abstract class GoldenTestCase extends ESTestCase { private static final Logger logger = LogManager.getLogger(GoldenTestCase.class); private final Path baseFile; @@ -226,7 +227,7 @@ private List> doTests() throws IOException { } if (stages.contains(Stage.PHYSICAL_OPTIMIZATION) || stages.contains(Stage.LOCAL_PHYSICAL_OPTIMIZATION) - || stages.contains(Stage.NODE_REDUCE_OPTIMIZATION) + || stages.contains(Stage.NODE_REDUCE) || stages.contains(Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION)) { var physicalPlanOptimizer = new PhysicalPlanOptimizer( new PhysicalOptimizerContext(EsqlTestUtils.TEST_CFG, transportVersion) @@ -242,7 +243,7 @@ private List> doTests() throws IOException { TestResult localPhysicalResult = verifyOrWrite(localOptimize(physicalPlan, conf), Stage.LOCAL_PHYSICAL_OPTIMIZATION); result.add(Tuple.tuple(Stage.LOCAL_PHYSICAL_OPTIMIZATION, localPhysicalResult)); } - if (stages.contains(Stage.NODE_REDUCE_OPTIMIZATION) || stages.contains(Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION)) { + if (stages.contains(Stage.NODE_REDUCE) || stages.contains(Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION)) { ExchangeExec exec = EsqlTestUtils.singleValue(physicalPlan.collect(ExchangeExec.class)); var sink = new ExchangeSinkExec(exec.source(), exec.output(), false, exec.child()); var reductionPlan = ComputeService.reductionPlan( @@ -256,16 +257,24 @@ private List> doTests() throws IOException { new PlanTimeProfile() ); - if (stages.contains(Stage.NODE_REDUCE_OPTIMIZATION)) { - result.addAll(addDualPlanResult(Stage.NODE_REDUCE_OPTIMIZATION, reductionPlan, "node_reduce", "data")); + if (stages.contains(Stage.NODE_REDUCE)) { + var dualFileOutput = (DualFileOutput) Stage.NODE_REDUCE.fileOutput; + result.addAll( + addDualPlanResult( + Stage.NODE_REDUCE, + reductionPlan, + dualFileOutput.nodeReduceOutput(), + dualFileOutput.dataNodeOutput() + ) + ); } - // FIXME(gal, NOCOMMIT) Simplify this, this shouldn't only perform the local optimization on the data plan. if (stages.contains(Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION)) { + var dualFileOutput = (DualFileOutput) Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION.fileOutput; switch (reductionPlan.nodeReduceLocalPhysicalOptimization()) { - // FIXME(gal, NOCOMMIT) document + // If there is no local node-reduce physical optimization, there's nothing to verify! case DISABLED -> { var foo = localOptimize(reductionPlan.dataNodePlan(), conf); - var bar = verifyOrWrite(foo, outputPath("reduction_", "local_data")); + var bar = verifyOrWrite(foo, outputPath(dualFileOutput.dataNodeOutput())); result.add(Tuple.tuple(Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION, bar)); } case ENABLED -> { @@ -278,8 +287,8 @@ private List> doTests() throws IOException { addDualPlanResult( Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION, finalizedResult, - "local_node_reduce", - "local_data" + dualFileOutput.nodeReduceOutput(), + dualFileOutput.dataNodeOutput() ) ); } @@ -302,8 +311,8 @@ private List> addDualPlanResult( String nodeReduceName, String dataNodeName ) throws IOException { - var reduceResult = verifyOrWrite(plan.nodeReducePlan(), outputPath("reduction_", nodeReduceName)); - var dataResult = verifyOrWrite(plan.dataNodePlan(), outputPath("reduction_", dataNodeName)); + var reduceResult = verifyOrWrite(plan.nodeReducePlan(), outputPath(nodeReduceName)); + var dataResult = verifyOrWrite(plan.dataNodePlan(), outputPath(dataNodeName)); var result = new ArrayList>(); if (reduceResult == TestResult.FAILURE || dataResult == TestResult.FAILURE) { result.add(Tuple.tuple(stage, TestResult.FAILURE)); @@ -340,14 +349,14 @@ private > TestResult verifyOrWrite(T plan, Path outputFil } private Path outputPath(Stage stage) { - return outputPath("", stage.name().toLowerCase(Locale.ROOT)); + return outputPath(((SingleFileOutput) stage.fileOutput).output()); } - private Path outputPath(String prefix, String suffix) { + private Path outputPath(String stageName) { var paths = new String[nestedPath.length + 2]; paths[0] = testName; System.arraycopy(nestedPath, 0, paths, 1, nestedPath.length); - paths[paths.length - 1] = Strings.format("%s%s.expected", prefix, suffix); + paths[paths.length - 1] = Strings.format("%s.expected", stageName); return PathUtils.get(basePath.toString(), paths); } @@ -365,6 +374,9 @@ private PhysicalPlan localOptimize(PhysicalPlan plan, Configuration conf) { } private static Test.TestResult createNewOutput(Path output, QueryPlan plan) throws IOException { + if (output.toString().contains("extra")) { + throw new IllegalStateException("Extra output files should not be created automatically:" + output); + } Files.writeString(output, toString(plan), StandardCharsets.UTF_8); return Test.TestResult.CREATED; } @@ -408,30 +420,50 @@ protected List filteredWarnings() { return withDefaultLimitWarning(super.filteredWarnings()); } + private sealed interface StageOutput {} + + private record SingleFileOutput(String output) implements StageOutput {} + + private record DualFileOutput(String nodeReduceOutput, String dataNodeOutput) implements StageOutput {} + protected enum Stage { /** See {@link Analyzer}. */ - ANALYSIS, + ANALYSIS(new SingleFileOutput("analysis")), /** See {@link LogicalPlanOptimizer}. */ - LOGICAL_OPTIMIZATION, + LOGICAL_OPTIMIZATION(new SingleFileOutput("logical_optimization")), /** See {@link PhysicalPlanOptimizer}. */ - PHYSICAL_OPTIMIZATION, + PHYSICAL_OPTIMIZATION(new SingleFileOutput("physical_optimization")), /** * See {@link LocalPhysicalPlanOptimizer}. There's no LOCAL_LOGICAL here since in production we use PlannerUtils.localPlan to * produce the local physical plan directly from non-local physical plan. */ - LOCAL_PHYSICAL_OPTIMIZATION, + LOCAL_PHYSICAL_OPTIMIZATION(new SingleFileOutput("local_physical_optimization")), /** * See {@link ComputeService#reductionPlan}. Actually results in two plans: one for the node reduce driver and one for the * data nodes. */ - NODE_REDUCE_OPTIMIZATION, + NODE_REDUCE(new DualFileOutput("local_reduce_planned_reduce_driver", "local_reduce_planned_data_driver")), /** - * A combination of {@link Stage#NODE_REDUCE_OPTIMIZATION} and {@link Stage#LOCAL_PHYSICAL_OPTIMIZATION}: first produce the node + * A combination of {@link Stage#NODE_REDUCE} and {@link Stage#LOCAL_PHYSICAL_OPTIMIZATION}: first produce the node * reduce and data node plans, and then perform local physical optimization on both. */ - NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION + NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION( + new DualFileOutput("local_reduce_physical_optimization_reduce_driver", "local_reduce_physical_optimization_data_driver") + ); + + private final StageOutput fileOutput; + + Stage(StageOutput fileOutput) { + this.fileOutput = fileOutput; + } } + private sealed interface TestOutput {} + + private record SingleTestOutput(String output) implements TestOutput {} + + private record DualTestOutput(String nodeReduceOutput, String dataNodeOutput) implements TestOutput {} + private static String normalize(String s) { return s.lines().map(String::strip).collect(Collectors.joining("\n")); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlannerGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlannerGoldenTests.java index c27e6de78f056..8c0f139aadc7a 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlannerGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/LateMaterializationPlannerGoldenTests.java @@ -16,7 +16,7 @@ public class LateMaterializationPlannerGoldenTests extends GoldenTestCase { private static final EnumSet STAGES = EnumSet.of( Stage.PHYSICAL_OPTIMIZATION, - Stage.NODE_REDUCE_OPTIMIZATION, + Stage.NODE_REDUCE, Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION ); @@ -63,7 +63,7 @@ public void testMultipleFieldSortTopN() throws Exception { runGoldenTest(query, STAGES, unindexedStats()); } - public void testExpressionSortTopN() throws Exception { + public void testExpressionSortTopNKeepBeforeSort() throws Exception { String query = """ FROM employees | keep hire_date, height @@ -73,6 +73,16 @@ public void testExpressionSortTopN() throws Exception { runGoldenTest(query, STAGES, unindexedStats()); } + public void testExpressionSortTopNKeepAfterSort() throws Exception { + String query = """ + FROM employees + | SORT sin(height) * 2 + | keep hire_date + | LIMIT 20 + """; + runGoldenTest(query, STAGES, unindexedStats()); + } + public void testPushedDownTopN() throws Exception { String query = """ FROM employees diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_local_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/reduction_node_reduce.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_node_reduce.expected deleted file mode 100644 index d23a70cf756e6..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_node_reduce.expected +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by$0$0{r}],false] -\_ProjectExec[[height{f}, hire_date{f}, $$order_by$0$0{r}]] - \_FieldExtractExec[hire_date{f}]<[],[]> - \_TopNExec[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],44] - \_ExchangeSourceExec[[_doc{f}, height{f}, $$order_by$0$0{r}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected similarity index 73% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected index 843bf41435308..830cf56ade52d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_local_data.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by$0$0{r}],false] -\_ProjectExec[[_doc{f}, height{f}, $$order_by$0$0{r}]] +ExchangeSinkExec[[hire_date{f}, $$order_by$0$0{r}],false] +\_ProjectExec[[_doc{f}, $$order_by$0$0{r}]] \_TopNExec[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],36] \_EvalExec[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$0]] \_FieldExtractExec[height{f}]<[],[]> diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected similarity index 84% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected index 79ce101ea8de7..aa8139d1c1f41 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/reduction_data.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by$0$0{r}],false] +ExchangeSinkExec[[hire_date{f}, $$order_by$0$0{r}],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, height{f}, $$order_by$0$0{r}]] +Project[[_doc{f}, $$order_by$0$0{r}]] \_TopN[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],false] \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$0]] \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected new file mode 100644 index 0000000000000..c80d2a2b96cfe --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[hire_date{f}, $$order_by$0$0{r}],false] +\_ProjectExec[[hire_date{f}, $$order_by$0$0{r}]] + \_FieldExtractExec[hire_date{f}]<[],[]> + \_TopNExec[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}, $$order_by$0$0{r}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected similarity index 81% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/physical_optimization.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected index 10cc006e32b1b..b0412e9185ba3 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}, height{f}]] +ProjectExec[[hire_date{f}]] \_TopNExec[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[height{f}, hire_date{f}, $$order_by$0$0{r}],false] + \_ExchangeExec[[hire_date{f}, $$order_by$0$0{r}],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[height{f}, hire_date{f}, $$order_by$0$0{r}]] +Project[[hire_date{f}, $$order_by$0$0{r}]] \_TopN[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],false] \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$0]] \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/query.esql new file mode 100644 index 0000000000000..97b426ab3ee96 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/query.esql @@ -0,0 +1,4 @@ +FROM employees +| SORT sin(height) * 2 +| keep hire_date +| LIMIT 20 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected new file mode 100644 index 0000000000000..c3f5fe614747f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected @@ -0,0 +1,6 @@ +ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by$0$1{r}],false] +\_ProjectExec[[_doc{f}, height{f}, $$order_by$0$1{r}]] + \_TopNExec[[Order[$$order_by$0$1{r},ASC,LAST]],20[INTEGER],36] + \_EvalExec[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$1]] + \_FieldExtractExec[height{f}]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected new file mode 100644 index 0000000000000..7d646f2bfd4b7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected @@ -0,0 +1,6 @@ +ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by$0$1{r}],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}, height{f}, $$order_by$0$1{r}]] +\_TopN[[Order[$$order_by$0$1{r},ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$1]] + \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected new file mode 100644 index 0000000000000..4eb53127fc9c8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected @@ -0,0 +1,5 @@ +ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by$0$1{r}],false] +\_ProjectExec[[height{f}, hire_date{f}, $$order_by$0$1{r}]] + \_FieldExtractExec[hire_date{f}]<[],[]> + \_TopNExec[[Order[$$order_by$0$1{r},ASC,LAST]],20[INTEGER],44] + \_ExchangeSourceExec[[_doc{f}, height{f}, $$order_by$0$1{r}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected new file mode 100644 index 0000000000000..12d0908ec7c1d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected @@ -0,0 +1,8 @@ +ProjectExec[[hire_date{f}, height{f}]] +\_TopNExec[[Order[$$order_by$0$1{r},ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[height{f}, hire_date{f}, $$order_by$0$1{r}],false] + \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[height{f}, hire_date{f}, $$order_by$0$1{r}]] +\_TopN[[Order[$$order_by$0$1{r},ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$1]] + \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopN/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_local_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/reduction_node_reduce.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_local_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/reduction_node_reduce.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_local_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/reduction_node_reduce.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_local_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_local_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_local_node_reduce.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/reduction_node_reduce.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_local_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/reduction_node_reduce.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_local_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/reduction_node_reduce.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_local_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/reduction_node_reduce.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_local_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_local_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_data.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_data.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_node_reduce.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/reduction_node_reduce.expected rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected From a0eace366b2eec777fe4c05436109fa82d497a97 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 2 Feb 2026 21:52:36 +0200 Subject: [PATCH 009/137] Fix bug with synthetic names --- .../xpack/esql/optimizer/GoldenTestCase.java | 7 ++++++- ...l_reduce_physical_optimization_data_driver.expected | 8 ++++---- .../local_reduce_planned_data_driver.expected | 8 ++++---- .../local_reduce_planned_reduce_driver.expected | 8 ++++---- .../physical_optimization.expected | 10 +++++----- ...l_reduce_physical_optimization_data_driver.expected | 8 ++++---- .../local_reduce_planned_data_driver.expected | 8 ++++---- .../local_reduce_planned_reduce_driver.expected | 8 ++++---- .../physical_optimization.expected | 10 +++++----- 9 files changed, 40 insertions(+), 35 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 4976d5e1db864..483582f999214 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -382,9 +382,14 @@ private static Test.TestResult createNewOutput(Path output, QueryPlan plan) t } private static String toString(Node plan) { - return IDENTIFIER_PATTERN.matcher(plan.toString(Node.NodeStringFormat.FULL)).replaceAll(""); + String planString = plan.toString(Node.NodeStringFormat.FULL); + String withoutSyntheticPatterns = SYNTHETIC_PATTERN.matcher(planString).replaceAll("\\$\\$$1"); + return IDENTIFIER_PATTERN.matcher(withoutSyntheticPatterns).replaceAll(""); } + // Matches synthetic names like $$alias$1$2#3, since those $digits are generated during the test run and may differ each time. The + // #digit are removed by the next pattern. + private static final Pattern SYNTHETIC_PATTERN = Pattern.compile("\\$\\$([^$\\s]+)(\\$\\d+)*(?=[{#])"); private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("#\\d+"); private static Test.TestResult verifyExisting(Path output, QueryPlan plan) throws IOException { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected index 830cf56ade52d..6c0cb294fc861 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[hire_date{f}, $$order_by$0$0{r}],false] -\_ProjectExec[[_doc{f}, $$order_by$0$0{r}]] - \_TopNExec[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],36] - \_EvalExec[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$0]] +ExchangeSinkExec[[hire_date{f}, $$order_by{r}],false] +\_ProjectExec[[_doc{f}, $$order_by{r}]] + \_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],36] + \_EvalExec[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] \_FieldExtractExec[height{f}]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected index aa8139d1c1f41..2c2c810fdcd5f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[hire_date{f}, $$order_by$0$0{r}],false] +ExchangeSinkExec[[hire_date{f}, $$order_by{r}],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, $$order_by$0$0{r}]] -\_TopN[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$0]] +Project[[_doc{f}, $$order_by{r}]] +\_TopN[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected index c80d2a2b96cfe..6122b8f73ddfa 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[hire_date{f}, $$order_by$0$0{r}],false] -\_ProjectExec[[hire_date{f}, $$order_by$0$0{r}]] +ExchangeSinkExec[[hire_date{f}, $$order_by{r}],false] +\_ProjectExec[[hire_date{f}, $$order_by{r}]] \_FieldExtractExec[hire_date{f}]<[],[]> - \_TopNExec[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, $$order_by$0$0{r}],false] \ No newline at end of file + \_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}, $$order_by{r}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected index b0412e9185ba3..379de6ff82e29 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected @@ -1,8 +1,8 @@ ProjectExec[[hire_date{f}]] -\_TopNExec[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[hire_date{f}, $$order_by$0$0{r}],false] +\_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[hire_date{f}, $$order_by{r}],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[hire_date{f}, $$order_by$0$0{r}]] -\_TopN[[Order[$$order_by$0$0{r},ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$0]] +Project[[hire_date{f}, $$order_by{r}]] +\_TopN[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected index c3f5fe614747f..abec74e514128 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by$0$1{r}],false] -\_ProjectExec[[_doc{f}, height{f}, $$order_by$0$1{r}]] - \_TopNExec[[Order[$$order_by$0$1{r},ASC,LAST]],20[INTEGER],36] - \_EvalExec[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$1]] +ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by{r}],false] +\_ProjectExec[[_doc{f}, height{f}, $$order_by{r}]] + \_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],36] + \_EvalExec[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] \_FieldExtractExec[height{f}]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected index 7d646f2bfd4b7..d6d06ec07d272 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by$0$1{r}],false] +ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by{r}],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, height{f}, $$order_by$0$1{r}]] -\_TopN[[Order[$$order_by$0$1{r},ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$1]] +Project[[_doc{f}, height{f}, $$order_by{r}]] +\_TopN[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected index 4eb53127fc9c8..e19d24b8b2b9f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by$0$1{r}],false] -\_ProjectExec[[height{f}, hire_date{f}, $$order_by$0$1{r}]] +ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by{r}],false] +\_ProjectExec[[height{f}, hire_date{f}, $$order_by{r}]] \_FieldExtractExec[hire_date{f}]<[],[]> - \_TopNExec[[Order[$$order_by$0$1{r},ASC,LAST]],20[INTEGER],44] - \_ExchangeSourceExec[[_doc{f}, height{f}, $$order_by$0$1{r}],false] \ No newline at end of file + \_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],44] + \_ExchangeSourceExec[[_doc{f}, height{f}, $$order_by{r}],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected index 12d0908ec7c1d..dd1f613d8bedf 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected @@ -1,8 +1,8 @@ ProjectExec[[hire_date{f}, height{f}]] -\_TopNExec[[Order[$$order_by$0$1{r},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[height{f}, hire_date{f}, $$order_by$0$1{r}],false] +\_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[height{f}, hire_date{f}, $$order_by{r}],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[height{f}, hire_date{f}, $$order_by$0$1{r}]] -\_TopN[[Order[$$order_by$0$1{r},ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by$0$1]] +Project[[height{f}, hire_date{f}, $$order_by{r}]] +\_TopN[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file From 5fec441c9624682415375d20e7de531ae4b6843d Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 3 Feb 2026 14:41:51 +0200 Subject: [PATCH 010/137] Add name IDs --- .../xpack/esql/optimizer/GoldenTestCase.java | 62 ++++++++++++++++--- .../local_physical_optimization.expected | 26 ++++---- .../local_physical_optimization.expected | 26 ++++---- .../local_physical_optimization.expected | 26 ++++---- .../local_physical_optimization.expected | 18 +++--- .../local_physical_optimization.expected | 18 +++--- .../local_physical_optimization.expected | 18 +++--- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 12 ++-- .../local_physical_optimization.expected | 12 ++-- .../local_physical_optimization.expected | 12 ++-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 10 +-- .../local_physical_optimization.expected | 10 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 10 +-- .../local_physical_optimization.expected | 10 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 10 +-- .../local_physical_optimization.expected | 10 +-- .../local_physical_optimization.expected | 12 ++-- .../local_physical_optimization.expected | 12 ++-- .../local_physical_optimization.expected | 12 ++-- .../local_physical_optimization.expected | 14 ++--- .../local_physical_optimization.expected | 14 ++--- .../local_physical_optimization.expected | 36 +++++------ .../byte/local_physical_optimization.expected | 8 +-- .../date/local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../long/local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 26 ++++---- ...physical_optimization_data_driver.expected | 8 +-- .../local_reduce_planned_data_driver.expected | 8 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 +-- .../physical_optimization.expected | 12 ++-- ...physical_optimization_data_driver.expected | 12 ++-- .../local_reduce_planned_data_driver.expected | 10 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 +-- .../physical_optimization.expected | 14 ++--- ...physical_optimization_data_driver.expected | 12 ++-- .../local_reduce_planned_data_driver.expected | 10 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 +-- .../physical_optimization.expected | 14 ++--- ...physical_optimization_data_driver.expected | 18 +++--- .../local_reduce_planned_data_driver.expected | 16 ++--- ...ocal_reduce_planned_reduce_driver.expected | 10 +-- .../physical_optimization.expected | 18 +++--- ...physical_optimization_data_driver.expected | 8 +-- .../local_reduce_planned_data_driver.expected | 8 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 +-- .../physical_optimization.expected | 12 ++-- ...physical_optimization_data_driver.expected | 8 +-- .../local_reduce_planned_data_driver.expected | 8 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 +-- .../physical_optimization.expected | 14 ++--- ...physical_optimization_data_driver.expected | 14 ++--- ...ysical_optimization_reduce_driver.expected | 6 +- .../local_reduce_planned_data_driver.expected | 12 ++-- ...ocal_reduce_planned_reduce_driver.expected | 6 +- .../physical_optimization.expected | 14 ++--- ...physical_optimization_data_driver.expected | 8 +-- .../local_reduce_planned_data_driver.expected | 8 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 +-- .../physical_optimization.expected | 12 ++-- ...physical_optimization_data_driver.expected | 8 +-- .../local_reduce_planned_data_driver.expected | 10 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 +-- .../physical_optimization.expected | 14 ++--- ...physical_optimization_data_driver.expected | 8 +-- .../local_reduce_planned_data_driver.expected | 8 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 +-- .../physical_optimization.expected | 16 ++--- ...physical_optimization_data_driver.expected | 8 +-- .../local_reduce_planned_data_driver.expected | 8 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 +-- .../physical_optimization.expected | 12 ++-- 87 files changed, 547 insertions(+), 503 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 483582f999214..e6f833bad54c6 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -28,6 +28,7 @@ import org.elasticsearch.xpack.esql.analysis.UnmappedResolution; import org.elasticsearch.xpack.esql.core.expression.FoldContext; import org.elasticsearch.xpack.esql.core.tree.Node; +import org.elasticsearch.xpack.esql.core.util.Holder; import org.elasticsearch.xpack.esql.expression.function.EsqlFunctionRegistry; import org.elasticsearch.xpack.esql.inference.InferenceResolution; import org.elasticsearch.xpack.esql.parser.EsqlParser; @@ -57,7 +58,10 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.EnumSet; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -377,23 +381,63 @@ private static Test.TestResult createNewOutput(Path output, QueryPlan plan) t if (output.toString().contains("extra")) { throw new IllegalStateException("Extra output files should not be created automatically:" + output); } - Files.writeString(output, toString(plan), StandardCharsets.UTF_8); + Files.writeString(output, normalizeNameIds(plan), StandardCharsets.UTF_8); return Test.TestResult.CREATED; } - private static String toString(Node plan) { - String planString = plan.toString(Node.NodeStringFormat.FULL); - String withoutSyntheticPatterns = SYNTHETIC_PATTERN.matcher(planString).replaceAll("\\$\\$$1"); - return IDENTIFIER_PATTERN.matcher(withoutSyntheticPatterns).replaceAll(""); + private static String normalizeNameIds(Node plan) { + String full = plan.toString(Node.NodeStringFormat.FULL); + // full = normalizeSyntheticNames(full); + Matcher matcher = IDENTIFIER_PATTERN.matcher(full); + StringBuilder sb = new StringBuilder(); + int lastEnd = 0; + Holder counterHolder = new Holder<>(0); + Map idMap = new HashMap<>(); + while (matcher.find()) { + sb.append(full, lastEnd, matcher.start()); + int originalId = Integer.parseInt(matcher.group().substring(1)); // Drop the initial '#' prefix + int newId = idMap.computeIfAbsent(originalId, k -> { + int current = counterHolder.get(); + counterHolder.set(current + 1); + return current; + }); + sb.append("#").append(newId); + lastEnd = matcher.end(); + } + sb.append(full, lastEnd, full.length()); + return sb.toString(); + } + + /** + * Normalizes synthetic attribute names of the form $$something($something)* that are followed by # (node id). + * Replaces them with $$firstSegment$runningInt so golden output is stable across runs. + */ + private static String normalizeSyntheticNames(String full) { + Matcher matcher = SYNTHETIC_PATTERN.matcher(full); + StringBuilder sb = new StringBuilder(); + int lastEnd = 0; + Holder runningInt = new Holder<>(0); + Map idMap = new HashMap<>(); + while (matcher.find()) { + sb.append(full, lastEnd, matcher.start()); + String firstSegment = matcher.group(1); + int newId = idMap.computeIfAbsent(firstSegment, k -> { + int current = runningInt.get(); + runningInt.set(current + 1); + return current; + }); + sb.append("$$").append(firstSegment).append("$").append(newId); + lastEnd = matcher.end(); + } + sb.append(full, lastEnd, full.length()); + return sb.toString(); } - // Matches synthetic names like $$alias$1$2#3, since those $digits are generated during the test run and may differ each time. The - // #digit are removed by the next pattern. - private static final Pattern SYNTHETIC_PATTERN = Pattern.compile("\\$\\$([^$\\s]+)(\\$\\d+)*(?=[{#])"); + private static final Pattern SYNTHETIC_PATTERN = Pattern.compile("\\$\\$([^$\\s]+)(\\$\\d+)+(?=[{#])"); private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("#\\d+"); private static Test.TestResult verifyExisting(Path output, QueryPlan plan) throws IOException { - String testString = normalize(toString(plan)); + String testString = normalize(normalizeNameIds(plan)); if (testString.equals(normalize(Files.readString(output)))) { if (System.getProperty("golden.cleanactual") != null) { Path path = actualPath(output); diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected index 961fe3106b9dd..504e54c3064ee 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected @@ -1,13 +1,13 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],SINGLE,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_EvalExec[[BUCKET(date{r},P1D[DATE_PERIOD]) AS x]] - \_MergeExec[[date{r}]] - |_ProjectExec[[date{f}]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],SINGLE,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_EvalExec[[BUCKET(date{r}#4,P1D[DATE_PERIOD]) AS x#0]] + \_MergeExec[[date{r}#4]] + |_ProjectExec[[date{f}#5]] | \_LimitExec[1000[INTEGER],null] - | \_ExchangeExec[[date{f}],false] - | \_ProjectExec[[date{f}]] - | \_FieldExtractExec[date{f}]<[],[]> - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ + | \_ExchangeExec[[date{f}#5],false] + | \_ProjectExec[[date{f}#5]] + | \_FieldExtractExec[date{f}#5]<[],[]> + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#6], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "integer", "next" : { @@ -21,12 +21,12 @@ LimitExec[1000[INTEGER],null] "source" : "integer > 100@2:15" } }, tags=[]]]] - \_ProjectExec[[date{f}]] + \_ProjectExec[[date{f}#7]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[date{f}],false] - \_ProjectExec[[date{f}]] - \_FieldExtractExec[date{f}]<[],[]> - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ + \_ExchangeExec[[date{f}#7],false] + \_ProjectExec[[date{f}#7]] + \_FieldExtractExec[date{f}#7]<[],[]> + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "match" : { "keyword" : { "query" : "keyword", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected index 427b439ba70cb..72dbdcc974f68 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected @@ -1,13 +1,13 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],SINGLE,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_EvalExec[[DATETRUNC(P1D[DATE_PERIOD],date{r}) AS x]] - \_MergeExec[[date{r}]] - |_ProjectExec[[date{f}]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],SINGLE,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_EvalExec[[DATETRUNC(P1D[DATE_PERIOD],date{r}#4) AS x#0]] + \_MergeExec[[date{r}#4]] + |_ProjectExec[[date{f}#5]] | \_LimitExec[1000[INTEGER],null] - | \_ExchangeExec[[date{f}],false] - | \_ProjectExec[[date{f}]] - | \_FieldExtractExec[date{f}]<[],[]> - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ + | \_ExchangeExec[[date{f}#5],false] + | \_ProjectExec[[date{f}#5]] + | \_FieldExtractExec[date{f}#5]<[],[]> + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#6], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "integer", "next" : { @@ -21,12 +21,12 @@ LimitExec[1000[INTEGER],null] "source" : "integer > 100@2:15" } }, tags=[]]]] - \_ProjectExec[[date{f}]] + \_ProjectExec[[date{f}#7]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[date{f}],false] - \_ProjectExec[[date{f}]] - \_FieldExtractExec[date{f}]<[],[]> - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ + \_ExchangeExec[[date{f}#7],false] + \_ProjectExec[[date{f}#7]] + \_FieldExtractExec[date{f}#7]<[],[]> + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "match" : { "keyword" : { "query" : "keyword", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected index 668bab853e771..5c5cb8da952c2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected @@ -1,13 +1,13 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],SINGLE,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_EvalExec[[ROUNDTO(date{r},1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x]] - \_MergeExec[[date{r}]] - |_ProjectExec[[date{f}]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],SINGLE,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_EvalExec[[ROUNDTO(date{r}#4,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] + \_MergeExec[[date{r}#4]] + |_ProjectExec[[date{f}#5]] | \_LimitExec[1000[INTEGER],null] - | \_ExchangeExec[[date{f}],false] - | \_ProjectExec[[date{f}]] - | \_FieldExtractExec[date{f}]<[],[]> - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ + | \_ExchangeExec[[date{f}#5],false] + | \_ProjectExec[[date{f}#5]] + | \_FieldExtractExec[date{f}#5]<[],[]> + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#6], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "integer", "next" : { @@ -21,12 +21,12 @@ LimitExec[1000[INTEGER],null] "source" : "integer > 100@2:15" } }, tags=[]]]] - \_ProjectExec[[date{f}]] + \_ProjectExec[[date{f}#7]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[date{f}],false] - \_ProjectExec[[date{f}]] - \_FieldExtractExec[date{f}]<[],[]> - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ + \_ExchangeExec[[date{f}#7],false] + \_ProjectExec[[date{f}#7]] + \_FieldExtractExec[date{f}#7]<[],[]> + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "match" : { "keyword" : { "query" : "keyword", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected index 474d85c27e113..37d5c04ccc89b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected @@ -1,11 +1,11 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[ROUNDTO(date{f},1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x]] - \_FieldExtractExec[date{f}]<[],[]> - \_LookupJoinExec[[integer{f}],[language_code{f}],[],null] - |_FieldExtractExec[integer{f}]<[],[]> - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[ROUNDTO(date{f}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] + \_FieldExtractExec[date{f}#6]<[],[]> + \_LookupJoinExec[[integer{f}#7],[language_code{f}#8],[],null] + |_FieldExtractExec[integer{f}#7]<[],[]> + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#9], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -EsRelation[languages_lookup][LOOKUP][language_code{f}]<>]] \ No newline at end of file +EsRelation[languages_lookup][LOOKUP][language_code{f}#8]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected index 474d85c27e113..37d5c04ccc89b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected @@ -1,11 +1,11 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[ROUNDTO(date{f},1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x]] - \_FieldExtractExec[date{f}]<[],[]> - \_LookupJoinExec[[integer{f}],[language_code{f}],[],null] - |_FieldExtractExec[integer{f}]<[],[]> - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[ROUNDTO(date{f}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] + \_FieldExtractExec[date{f}#6]<[],[]> + \_LookupJoinExec[[integer{f}#7],[language_code{f}#8],[],null] + |_FieldExtractExec[integer{f}#7]<[],[]> + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#9], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -EsRelation[languages_lookup][LOOKUP][language_code{f}]<>]] \ No newline at end of file +EsRelation[languages_lookup][LOOKUP][language_code{f}#8]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected index 474d85c27e113..37d5c04ccc89b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected @@ -1,11 +1,11 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[ROUNDTO(date{f},1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x]] - \_FieldExtractExec[date{f}]<[],[]> - \_LookupJoinExec[[integer{f}],[language_code{f}],[],null] - |_FieldExtractExec[integer{f}]<[],[]> - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[ROUNDTO(date{f}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] + \_FieldExtractExec[date{f}#6]<[],[]> + \_LookupJoinExec[[integer{f}#7],[language_code{f}#8],[],null] + |_FieldExtractExec[integer{f}#7]<[],[]> + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#9], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -EsRelation[languages_lookup][LOOKUP][language_code{f}]<>]] \ No newline at end of file +EsRelation[languages_lookup][LOOKUP][language_code{f}#8]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/local_physical_optimization.expected index ef1ef15736930..452b37138c025 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/local_physical_optimization.expected index f5a5c391169bb..b1eba3348e69d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/round_to/local_physical_optimization.expected index cf999b9b04435..ee48e2b81fe3e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/round_to/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/local_physical_optimization.expected index ef1ef15736930..452b37138c025 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/local_physical_optimization.expected index f5a5c391169bb..b1eba3348e69d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/round_to/local_physical_optimization.expected index cf999b9b04435..ee48e2b81fe3e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/round_to/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected index 63a896f2a8f23..9bed443f7dbca 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected @@ -1,10 +1,10 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[SUM(long{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long), COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[SUM(long{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long), COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],24] - \_FieldExtractExec[long{f}]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] + \_ExchangeExec[[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],true] + \_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] + \_FieldExtractExec[long{f}#1]<[],[]> + \_EvalExec[[$$date$round_to$datetime{f}#12 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#13, $$date$round_to$datetime{f}#12], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected index 0605eac068d20..8a37befcc7c7e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected @@ -1,10 +1,10 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[SUM(long{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long), COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[SUM(long{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long), COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],24] - \_FieldExtractExec[long{f}]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] + \_ExchangeExec[[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],true] + \_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] + \_FieldExtractExec[long{f}#1]<[],[]> + \_EvalExec[[$$date$round_to$datetime{f}#12 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#13, $$date$round_to$datetime{f}#12], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected index 6b66c077f925b..dd6350bd70a36 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected @@ -1,10 +1,10 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[SUM(long{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long), COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[SUM(long{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long), COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],24] - \_FieldExtractExec[long{f}]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] + \_ExchangeExec[[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],true] + \_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] + \_FieldExtractExec[long{f}#1]<[],[]> + \_EvalExec[[$$date$round_to$datetime{f}#12 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#13, $$date$round_to$datetime{f}#12], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/local_physical_optimization.expected index dc56c28f87e93..6af84798b0c5b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "range" : { "date" : { @@ -42,4 +42,4 @@ LimitExec[1000[INTEGER],null] "boost" : 0.0 } } -}, tags=[1698019200000]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[1698019200000]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected index 395483c2bb606..8b039c4db5c27 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected index fa6cea028e09c..1783e8bca9fb9 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/local_physical_optimization.expected index dc56c28f87e93..6af84798b0c5b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "range" : { "date" : { @@ -42,4 +42,4 @@ LimitExec[1000[INTEGER],null] "boost" : 0.0 } } -}, tags=[1698019200000]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[1698019200000]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected index b2f7f6047fbc3..741c5cc853d00 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected index 479e0224b6622..ba745f8603cf2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/local_physical_optimization.expected index dc56c28f87e93..6af84798b0c5b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "range" : { "date" : { @@ -42,4 +42,4 @@ LimitExec[1000[INTEGER],null] "boost" : 0.0 } } -}, tags=[1698019200000]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[1698019200000]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected index 23b908e99a46f..3bb91af178169 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected index 186576dc41e63..0adf9b4716949 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected index ccee8d2c5df22..54ec4005471fb 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected @@ -1,10 +1,10 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],long{f} > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10, x{r}],FINAL,[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],long{f} > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10, x{r}],INITIAL,[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],16] - \_FieldExtractExec[long{f}]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],FINAL,[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],null] + \_ExchangeExec[[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],INITIAL,[x{r}#0, $$count(*) where long > 10$count{r}#5, $$count(*) where long > 10$seen{r}#6],16] + \_FieldExtractExec[long{f}#1]<[],[]> + \_EvalExec[[$$date$round_to$datetime{f}#7 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8, $$date$round_to$datetime{f}#7], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected index 8fcf95e865e7b..8665d69bc4af1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected @@ -1,10 +1,10 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],long{f} > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10, x{r}],FINAL,[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],long{f} > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10, x{r}],INITIAL,[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],16] - \_FieldExtractExec[long{f}]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],FINAL,[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],null] + \_ExchangeExec[[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],INITIAL,[x{r}#0, $$count(*) where long > 10$count{r}#5, $$count(*) where long > 10$seen{r}#6],16] + \_FieldExtractExec[long{f}#1]<[],[]> + \_EvalExec[[$$date$round_to$datetime{f}#7 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8, $$date$round_to$datetime{f}#7], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected index 01cb9eab075bb..d59fd1a30f5dc 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected @@ -1,10 +1,10 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],long{f} > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10, x{r}],FINAL,[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],long{f} > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10, x{r}],INITIAL,[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],16] - \_FieldExtractExec[long{f}]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],FINAL,[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],null] + \_ExchangeExec[[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],INITIAL,[x{r}#0, $$count(*) where long > 10$count{r}#5, $$count(*) where long > 10$seen{r}#6],16] + \_FieldExtractExec[long{f}#1]<[],[]> + \_EvalExec[[$$date$round_to$datetime{f}#7 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8, $$date$round_to$datetime{f}#7], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected index 046b0b2603e13..f4aec5a235e42 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[!alias_integer, date{f}, x{r}]] -\_TopNExec[[Order[date{f},ASC,LAST]],5[INTEGER],null] - \_ExchangeExec[[!alias_integer, date{f}, x{r}],false] - \_ProjectExec[[!alias_integer, date{f}, x{r}]] +ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] +\_TopNExec[[Order[date{f}#0,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[!alias_integer, date{f}#0, x{r}#1],false] + \_ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] \_FieldExtractExec[!alias_integer]<[],[]> - \_EvalExec[[ROUNDTO(date{f},1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x]] - \_FieldExtractExec[date{f}]<[],[]> - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[5], sort[[FieldSort[field=date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[1056] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file + \_EvalExec[[ROUNDTO(date{f}#0,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#1]] + \_FieldExtractExec[date{f}#0]<[],[]> + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#2], limit[5], sort[[FieldSort[field=date{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[1056] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected index 046b0b2603e13..f4aec5a235e42 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[!alias_integer, date{f}, x{r}]] -\_TopNExec[[Order[date{f},ASC,LAST]],5[INTEGER],null] - \_ExchangeExec[[!alias_integer, date{f}, x{r}],false] - \_ProjectExec[[!alias_integer, date{f}, x{r}]] +ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] +\_TopNExec[[Order[date{f}#0,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[!alias_integer, date{f}#0, x{r}#1],false] + \_ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] \_FieldExtractExec[!alias_integer]<[],[]> - \_EvalExec[[ROUNDTO(date{f},1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x]] - \_FieldExtractExec[date{f}]<[],[]> - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[5], sort[[FieldSort[field=date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[1056] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file + \_EvalExec[[ROUNDTO(date{f}#0,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#1]] + \_FieldExtractExec[date{f}#0]<[],[]> + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#2], limit[5], sort[[FieldSort[field=date{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[1056] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected index 689d91b4b0781..d6af15a5d5b6f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected @@ -1,14 +1,14 @@ LimitExec[1000[INTEGER],null] -\_MergeExec[[x{r}, y{r}, hd{r}, _fork{r}]] - |_ProjectExec[[x{r}, y{r}, hd{r}, _fork{r}]] - | \_EvalExec[[fork1[KEYWORD] AS _fork]] +\_MergeExec[[x{r}#0, y{r}#1, hd{r}#2, _fork{r}#3]] + |_ProjectExec[[x{r}#4, y{r}#5, hd{r}#6, _fork{r}#7]] + | \_EvalExec[[fork1[KEYWORD] AS _fork#7]] | \_LimitExec[1000[INTEGER],null] - | \_AggregateExec[[hd{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x, MAX(long{f},true[BOOLEAN],PT0S[TIME_DURATION]) AS y, hd{r}],FINAL,[hd{r}, $$x$count{r}, $$x$seen{r}, $$y$max{r}, $$y$seen{r}],null] - | \_ExchangeExec[[hd{r}, $$x$count{r}, $$x$seen{r}, $$y$max{r}, $$y$seen{r}],true] - | \_AggregateExec[[hd{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x, MAX(long{f},true[BOOLEAN],PT0S[TIME_DURATION]) AS y, hd{r}],INITIAL,[hd{r}, $$x$count{r}, $$x$seen{r}, $$y$max{r}, $$y$seen{r}],24] - | \_FieldExtractExec[long{f}]<[],[]> - | \_EvalExec[[$$date$round_to$datetime{f} AS hd]] - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ + | \_AggregateExec[[hd{r}#6],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#4, MAX(long{f}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#5, hd{r}#6],FINAL,[hd{r}#6, $$x$count{r}#9, $$x$seen{r}#10, $$y$max{r}#11, $$y$seen{r}#12],null] + | \_ExchangeExec[[hd{r}#6, $$x$count{r}#9, $$x$seen{r}#10, $$y$max{r}#11, $$y$seen{r}#12],true] + | \_AggregateExec[[hd{r}#6],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#4, MAX(long{f}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#5, hd{r}#6],INITIAL,[hd{r}#6, $$x$count{r}#13, $$x$seen{r}#14, $$y$max{r}#15, $$y$seen{r}#16],24] + | \_FieldExtractExec[long{f}#8]<[],[]> + | \_EvalExec[[$$date$round_to$datetime{f}#17 AS hd#6]] + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#18, $$date$round_to$datetime{f}#17], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", "next" : { @@ -83,13 +83,13 @@ LimitExec[1000[INTEGER],null] "boost" : 1.0 } }, tags=[null]]]] - \_ProjectExec[[x{r}, y{r}, hd{r}, _fork{r}]] - \_EvalExec[[fork2[KEYWORD] AS _fork]] + \_ProjectExec[[x{r}#19, y{r}#20, hd{r}#21, _fork{r}#7]] + \_EvalExec[[fork2[KEYWORD] AS _fork#7]] \_LimitExec[1000[INTEGER],null] - \_AggregateExec[[hd{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x, MIN(long{f},true[BOOLEAN],PT0S[TIME_DURATION]) AS y, hd{r}],FINAL,[hd{r}, $$x$count{r}, $$x$seen{r}, $$y$min{r}, $$y$seen{r}],null] - \_ExchangeExec[[hd{r}, $$x$count{r}, $$x$seen{r}, $$y$min{r}, $$y$seen{r}],true] - \_AggregateExec[[hd{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x, MIN(long{f},true[BOOLEAN],PT0S[TIME_DURATION]) AS y, hd{r}],INITIAL,[hd{r}, $$x$count{r}, $$x$seen{r}, $$y$min{r}, $$y$seen{r}],24] - \_FieldExtractExec[long{f}]<[],[]> - \_EvalExec[[DATETRUNC(P2D[DATE_PERIOD],date{f}) AS hd]] - \_FieldExtractExec[date{f}]<[],[]> - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file + \_AggregateExec[[hd{r}#21],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#19, MIN(long{f}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#20, hd{r}#21],FINAL,[hd{r}#21, $$x$count{r}#23, $$x$seen{r}#24, $$y$min{r}#25, $$y$seen{r}#26],null] + \_ExchangeExec[[hd{r}#21, $$x$count{r}#23, $$x$seen{r}#24, $$y$min{r}#25, $$y$seen{r}#26],true] + \_AggregateExec[[hd{r}#21],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#19, MIN(long{f}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#20, hd{r}#21],INITIAL,[hd{r}#21, $$x$count{r}#27, $$x$seen{r}#28, $$y$min{r}#29, $$y$seen{r}#30],24] + \_FieldExtractExec[long{f}#22]<[],[]> + \_EvalExec[[DATETRUNC(P2D[DATE_PERIOD],date{f}#31) AS hd#21]] + \_FieldExtractExec[date{f}#31]<[],[]> + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#32], limit[], sort[] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/local_physical_optimization.expected index 23bb5e9c22897..5315aaeb6b782 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "byte", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/local_physical_optimization.expected index 50845a7e8de0e..a917d136623a5 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/local_physical_optimization.expected index 082cecd12d88a..66b986835d508 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date_nanos", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/local_physical_optimization.expected index 88f9a412070ba..d7f1b8f132836 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "double", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/local_physical_optimization.expected index 66daa7da9316f..299660977cb4e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "float", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/local_physical_optimization.expected index f4b5190ff7395..7f6523fa91e37 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "half_float", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/local_physical_optimization.expected index fba0ce864cf57..bd20ccd161980 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "integer", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/long/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/long/local_physical_optimization.expected index 45671a3481eff..cf3a620024a4e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/long/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/long/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "long", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/local_physical_optimization.expected index d2a0558821e41..c980fac8998ca 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "scaled_float", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/local_physical_optimization.expected index dda69d55339db..ad219641bde8c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "short", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected index 7dc015da213c7..9f3fe63e4a21f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected @@ -1,16 +1,16 @@ -ProjectExec[[x{r}, cnt{r}, date{r}]] +ProjectExec[[x{r}#0, cnt{r}#1, date{r}#2]] \_LimitExec[1000[INTEGER],null] - \_MergeExec[[alias_integer{r}, boolean{r}, byte{r}, constant_keyword-foo{r}, date{r}, date_nanos{r}, dense_vector{r}, double{r}, float{r}, half_float{r}, integer{r}, ip{r}, keyword{r}, long{r}, scaled_float{r}, semantic_text{r}, short{r}, text{r}, unsigned_long{r}, version{r}, wildcard{r}, cnt{r}, x{r}]] - |_ExchangeExec[[alias_integer{r}, boolean{f}, byte{f}, constant_keyword-foo{f}, date{f}, date_nanos{f}, dense_vector{f}, double{f}, float{f}, half_float{f}, integer{f}, ip{f}, keyword{f}, long{f}, scaled_float{f}, semantic_text{f}, short{f}, text{f}, unsigned_long{f}, version{f}, wildcard{f}, cnt{r}, x{r}],false] - | \_ProjectExec[[alias_integer{r}, boolean{f}, byte{f}, constant_keyword-foo{f}, date{f}, date_nanos{f}, dense_vector{f}, double{f}, float{f}, half_float{f}, integer{f}, ip{f}, keyword{f}, long{f}, scaled_float{f}, semantic_text{f}, short{f}, text{f}, unsigned_long{f}, version{f}, wildcard{f}, cnt{r}, x{r}]] - | \_FieldExtractExec[boolean{f}, byte{f}, constant_keyword-foo{f}, date{f}, date_nanos{f}, dense_vector{f}, double{f}, float{f}, half_float{f}, integer{f}, ip{f}, keyword{f}, long{f}, scaled_float{f}, semantic_text{f}, short{f}, text{f}, unsigned_long{f}, version{f}, wildcard{f}]<[],[]> - | \_EvalExec[[null[LONG] AS cnt, null[DATETIME] AS x, null[KEYWORD] AS alias_integer]] - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[6472] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] - \_ProjectExec[[alias_integer{r}, boolean{r}, byte{r}, constant_keyword-foo{r}, date{r}, date_nanos{r}, dense_vector{r}, double{r}, float{r}, half_float{r}, integer{r}, ip{r}, keyword{r}, long{r}, scaled_float{r}, semantic_text{r}, short{r}, text{r}, unsigned_long{r}, version{r}, wildcard{r}, cnt{r}, x{r}]] - \_EvalExec[[null[KEYWORD] AS alias_integer, null[BOOLEAN] AS boolean, null[INTEGER] AS byte, null[KEYWORD] AS constant_keyword-foo, null[DATETIME] AS date, null[DATE_NANOS] AS date_nanos, null[DENSE_VECTOR] AS dense_vector, null[DOUBLE] AS double, null[DOUBLE] AS float, null[DOUBLE] AS half_float, null[INTEGER] AS integer, null[IP] AS ip, null[KEYWORD] AS keyword, null[LONG] AS long, null[DOUBLE] AS scaled_float, null[TEXT] AS semantic_text, null[INTEGER] AS short, null[TEXT] AS text, null[UNSIGNED_LONG] AS unsigned_long, null[VERSION] AS version, null[KEYWORD] AS wildcard, null[KEYWORD] AS alias_integer]] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt, x{r}],FINAL,[x{r}, $$cnt$count{r}, $$cnt$seen{r}],null] - \_ExchangeExec[[x{r}, $$cnt$count{r}, $$cnt$seen{r}],true] - \_FilterExec[$$cnt$count{r} > 0[LONG]] + \_MergeExec[[alias_integer{r}#3, boolean{r}#4, byte{r}#5, constant_keyword-foo{r}#6, date{r}#2, date_nanos{r}#7, dense_vector{r}#8, double{r}#9, float{r}#10, half_float{r}#11, integer{r}#12, ip{r}#13, keyword{r}#14, long{r}#15, scaled_float{r}#16, semantic_text{r}#17, short{r}#18, text{r}#19, unsigned_long{r}#20, version{r}#21, wildcard{r}#22, cnt{r}#1, x{r}#0]] + |_ExchangeExec[[alias_integer{r}#23, boolean{f}#24, byte{f}#25, constant_keyword-foo{f}#26, date{f}#27, date_nanos{f}#28, dense_vector{f}#29, double{f}#30, float{f}#31, half_float{f}#32, integer{f}#33, ip{f}#34, keyword{f}#35, long{f}#36, scaled_float{f}#37, semantic_text{f}#38, short{f}#39, text{f}#40, unsigned_long{f}#41, version{f}#42, wildcard{f}#43, cnt{r}#44, x{r}#45],false] + | \_ProjectExec[[alias_integer{r}#23, boolean{f}#24, byte{f}#25, constant_keyword-foo{f}#26, date{f}#27, date_nanos{f}#28, dense_vector{f}#29, double{f}#30, float{f}#31, half_float{f}#32, integer{f}#33, ip{f}#34, keyword{f}#35, long{f}#36, scaled_float{f}#37, semantic_text{f}#38, short{f}#39, text{f}#40, unsigned_long{f}#41, version{f}#42, wildcard{f}#43, cnt{r}#44, x{r}#45]] + | \_FieldExtractExec[boolean{f}#24, byte{f}#25, constant_keyword-foo{f}#26, date{f}#27, date_nanos{f}#28, dense_vector{f}#29, double{f}#30, float{f}#31, half_float{f}#32, integer{f}#33, ip{f}#34, keyword{f}#35, long{f}#36, scaled_float{f}#37, semantic_text{f}#38, short{f}#39, text{f}#40, unsigned_long{f}#41, version{f}#42, wildcard{f}#43]<[],[]> + | \_EvalExec[[null[LONG] AS cnt#44, null[DATETIME] AS x#45, null[KEYWORD] AS alias_integer#23]] + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#46], limit[], sort[] estimatedRowSize[6472] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] + \_ProjectExec[[alias_integer{r}#47, boolean{r}#48, byte{r}#49, constant_keyword-foo{r}#50, date{r}#51, date_nanos{r}#52, dense_vector{r}#53, double{r}#54, float{r}#55, half_float{r}#56, integer{r}#57, ip{r}#58, keyword{r}#59, long{r}#60, scaled_float{r}#61, semantic_text{r}#62, short{r}#63, text{r}#64, unsigned_long{r}#65, version{r}#66, wildcard{r}#67, cnt{r}#68, x{r}#69]] + \_EvalExec[[null[KEYWORD] AS alias_integer#70, null[BOOLEAN] AS boolean#48, null[INTEGER] AS byte#49, null[KEYWORD] AS constant_keyword-foo#50, null[DATETIME] AS date#51, null[DATE_NANOS] AS date_nanos#52, null[DENSE_VECTOR] AS dense_vector#53, null[DOUBLE] AS double#54, null[DOUBLE] AS float#55, null[DOUBLE] AS half_float#56, null[INTEGER] AS integer#57, null[IP] AS ip#58, null[KEYWORD] AS keyword#59, null[LONG] AS long#60, null[DOUBLE] AS scaled_float#61, null[TEXT] AS semantic_text#62, null[INTEGER] AS short#63, null[TEXT] AS text#64, null[UNSIGNED_LONG] AS unsigned_long#65, null[VERSION] AS version#66, null[KEYWORD] AS wildcard#67, null[KEYWORD] AS alias_integer#47]] + \_AggregateExec[[x{r}#69],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt#68, x{r}#69],FINAL,[x{r}#69, $$cnt$count{r}#71, $$cnt$seen{r}#72],null] + \_ExchangeExec[[x{r}#69, $$cnt$count{r}#71, $$cnt$seen{r}#72],true] + \_FilterExec[$$cnt$count{r}#73 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -85,4 +85,4 @@ ProjectExec[[x{r}, cnt{r}, date{r}]] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$cnt$count{r}, $$cnt$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#69, $$cnt$count{r}#73, $$cnt$seen{r}#74], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected index 79d08e098a4ac..71c01677f83a5 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[_doc{f}, hire_date{f}]] - \_FieldExtractExec[hire_date{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[_doc{f}#3, hire_date{f}#1]] + \_FieldExtractExec[hire_date{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected index 42c2f1deccb35..fc4d011c9a8fb 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, hire_date{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#3, hire_date{f}#1]] +\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected index 378271a5e3f37..4b4fc0c891ac1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] - \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> + \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected index cd76be3897e14..84b502cae4e25 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[hire_date{f}, salary{f}, emp_no{f}]] -\_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}, hire_date{f}, salary{f}],false] +ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] +\_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, hire_date{f}, salary{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] +\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected index 6c0cb294fc861..b70e2da30d8d9 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[hire_date{f}, $$order_by{r}],false] -\_ProjectExec[[_doc{f}, $$order_by{r}]] - \_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],36] - \_EvalExec[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] - \_FieldExtractExec[height{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[hire_date{f}#0, $$order_by$0$1{r}#1],false] +\_ProjectExec[[_doc{f}#2, $$order_by$0$1{r}#1]] + \_TopNExec[[Order[$$order_by$0$1{r}#1,ASC,LAST]],20[INTEGER],36] + \_EvalExec[[SIN(height{f}#3) * 2[INTEGER] AS $$order_by$0$1#1]] + \_FieldExtractExec[height{f}#3]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#2], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected index 2c2c810fdcd5f..6e7579d93480f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[hire_date{f}, $$order_by{r}],false] +ExchangeSinkExec[[hire_date{f}#0, $$order_by$0$1{r}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, $$order_by{r}]] -\_TopN[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#2, $$order_by$0$1{r}#1]] +\_TopN[[Order[$$order_by$0$1{r}#1,ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}#3) * 2[INTEGER] AS $$order_by$0$1#1]] + \_EsRelation[employees][_doc{f}#2, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#3, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#0, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected index 6122b8f73ddfa..b69f8a120e20a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[hire_date{f}, $$order_by{r}],false] -\_ProjectExec[[hire_date{f}, $$order_by{r}]] - \_FieldExtractExec[hire_date{f}]<[],[]> - \_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, $$order_by{r}],false] \ No newline at end of file +ExchangeSinkExec[[hire_date{f}#0, $$order_by$0$1{r}#1],false] +\_ProjectExec[[hire_date{f}#0, $$order_by$0$1{r}#1]] + \_FieldExtractExec[hire_date{f}#0]<[],[]> + \_TopNExec[[Order[$$order_by$0$1{r}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#2, $$order_by$0$1{r}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected index 379de6ff82e29..40e41a83c3210 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}]] -\_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[hire_date{f}, $$order_by{r}],false] +ProjectExec[[hire_date{f}#0]] +\_TopNExec[[Order[$$order_by$0$1{r}#1,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[hire_date{f}#0, $$order_by$0$1{r}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[hire_date{f}, $$order_by{r}]] -\_TopN[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[hire_date{f}#0, $$order_by$0$1{r}#1]] +\_TopN[[Order[$$order_by$0$1{r}#1,ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}#2) * 2[INTEGER] AS $$order_by$0$1#1]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#2, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected index abec74e514128..d7b0d2e276b29 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by{r}],false] -\_ProjectExec[[_doc{f}, height{f}, $$order_by{r}]] - \_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],36] - \_EvalExec[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] - \_FieldExtractExec[height{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0$0{r}#2],false] +\_ProjectExec[[_doc{f}#3, height{f}#0, $$order_by$0$0{r}#2]] + \_TopNExec[[Order[$$order_by$0$0{r}#2,ASC,LAST]],20[INTEGER],36] + \_EvalExec[[SIN(height{f}#0) * 2[INTEGER] AS $$order_by$0$0#2]] + \_FieldExtractExec[height{f}#0]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected index d6d06ec07d272..44d16e2751dd8 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by{r}],false] +ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0$0{r}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, height{f}, $$order_by{r}]] -\_TopN[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#3, height{f}#0, $$order_by$0$0{r}#2]] +\_TopN[[Order[$$order_by$0$0{r}#2,ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}#0) * 2[INTEGER] AS $$order_by$0$0#2]] + \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#0, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected index e19d24b8b2b9f..45f5637b6faac 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by{r}],false] -\_ProjectExec[[height{f}, hire_date{f}, $$order_by{r}]] - \_FieldExtractExec[hire_date{f}]<[],[]> - \_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],44] - \_ExchangeSourceExec[[_doc{f}, height{f}, $$order_by{r}],false] \ No newline at end of file +ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0$0{r}#2],false] +\_ProjectExec[[height{f}#0, hire_date{f}#1, $$order_by$0$0{r}#2]] + \_FieldExtractExec[hire_date{f}#1]<[],[]> + \_TopNExec[[Order[$$order_by$0$0{r}#2,ASC,LAST]],20[INTEGER],44] + \_ExchangeSourceExec[[_doc{f}#3, height{f}#0, $$order_by$0$0{r}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected index dd1f613d8bedf..083b9f2af3acf 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}, height{f}]] -\_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[height{f}, hire_date{f}, $$order_by{r}],false] +ProjectExec[[hire_date{f}#0, height{f}#1]] +\_TopNExec[[Order[$$order_by$0$0{r}#2,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[height{f}#1, hire_date{f}#0, $$order_by$0$0{r}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[height{f}, hire_date{f}, $$order_by{r}]] -\_TopN[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[height{f}#1, hire_date{f}#0, $$order_by$0$0{r}#2]] +\_TopN[[Order[$$order_by$0$0{r}#2,ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}#1) * 2[INTEGER] AS $$order_by$0$0#2]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#1, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected index afa8bc120313d..ebbbae1cfcc6d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected @@ -1,11 +1,11 @@ -ExchangeSinkExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}],false] -\_ProjectExec[[_doc{f}, emp_no{f}, languages{f}, language_code{r}, language_name{f}]] - \_TopNExec[[Order[emp_no{f},ASC,LAST]],20[INTEGER],82] - \_FieldExtractExec[emp_no{f}]<[],[]> - \_LookupJoinExec[[language_code{r}],[language_code{f}],[language_name{f}],null] - |_EvalExec[[languages{f} AS language_code]] - | \_FieldExtractExec[languages{f}]<[],[]> - | \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query={ +ExchangeSinkExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] +\_ProjectExec[[_doc{f}#25, emp_no{f}#2, languages{f}#12, language_code{r}#23, language_name{f}#24]] + \_TopNExec[[Order[emp_no{f}#2,ASC,LAST]],20[INTEGER],82] + \_FieldExtractExec[emp_no{f}#2]<[],[]> + \_LookupJoinExec[[language_code{r}#23],[language_code{f}#26],[language_name{f}#24],null] + |_EvalExec[[languages{f}#12 AS language_code#23]] + | \_FieldExtractExec[languages{f}#12]<[],[]> + | \_EsQueryExec[employees], indexMode[standard], [_doc{f}#25], limit[], sort[] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "emp_no", "next" : { @@ -22,4 +22,4 @@ ExchangeSinkExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f} } }, tags=[]]]] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -EsRelation[languages_lookup][LOOKUP][language_code{f}, language_name{f}]<>]] \ No newline at end of file +EsRelation[languages_lookup][LOOKUP][language_code{f}#26, language_name{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected index ef61e922e587d..7ff68ac134d83 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected @@ -1,9 +1,9 @@ -ExchangeSinkExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}],false] +ExchangeSinkExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, emp_no{f}, languages{f}, language_code{r}, language_name{f}]] -\_TopN[[Order[emp_no{f},ASC,LAST]],20[INTEGER],false] - \_Join[LEFT,[language_code{r}],[language_code{f}],null] - |_Eval[[languages{f} AS language_code]] - | \_Filter[emp_no{f} >= 10091[INTEGER] AND emp_no{f} < 10094[INTEGER]] - | \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}, language_name{f}]<>]] \ No newline at end of file +Project[[_doc{f}#25, emp_no{f}#2, languages{f}#12, language_code{r}#23, language_name{f}#24]] +\_TopN[[Order[emp_no{f}#2,ASC,LAST]],20[INTEGER],false] + \_Join[LEFT,[language_code{r}#23],[language_code{f}#26],null] + |_Eval[[languages{f}#12 AS language_code#23]] + | \_Filter[emp_no{f}#2 >= 10091[INTEGER] AND emp_no{f}#2 < 10094[INTEGER]] + | \_EsRelation[employees][_doc{f}#25, avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#26, language_name{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected index 1c739d108e561..19c98b1780f37 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}],false] -\_ProjectExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}]] - \_FieldExtractExec[avg_worked_seconds{f}, birth_date{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<[],[]> - \_TopNExec[[Order[emp_no{f},ASC,LAST]],20[INTEGER],430] - \_ExchangeSourceExec[[_doc{f}, emp_no{f}, languages{f}, language_code{r}, language_name{f}],false] \ No newline at end of file +ExchangeSinkExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] +\_ProjectExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24]] + \_FieldExtractExec[avg_worked_seconds{f}#0, birth_date{f}#1, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<[],[]> + \_TopNExec[[Order[emp_no{f}#2,ASC,LAST]],20[INTEGER],430] + \_ExchangeSourceExec[[_doc{f}#25, emp_no{f}#2, languages{f}#12, language_code{r}#23, language_name{f}#24],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected index 6de9cdeb68a29..438c1c6d34382 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected @@ -1,10 +1,10 @@ -TopNExec[[Order[emp_no{f},ASC,LAST]],20[INTEGER],null] -\_ExchangeExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}],false] +TopNExec[[Order[emp_no{f}#0,ASC,LAST]],20[INTEGER],null] +\_ExchangeExec[[avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#0, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}]] -\_TopN[[Order[emp_no{f},ASC,LAST]],20[INTEGER],false] - \_Join[LEFT,[language_code{r}],[language_code{f}],null] - |_Eval[[languages{f} AS language_code]] - | \_Filter[emp_no{f} >= 10091[INTEGER] AND emp_no{f} < 10094[INTEGER]] - | \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}, language_name{f}]<>]] \ No newline at end of file +Project[[avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#0, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24]] +\_TopN[[Order[emp_no{f}#0,ASC,LAST]],20[INTEGER],false] + \_Join[LEFT,[language_code{r}#23],[language_code{f}#25],null] + |_Eval[[languages{f}#12 AS language_code#23]] + | \_Filter[emp_no{f}#0 >= 10091[INTEGER] AND emp_no{f}#0 < 10094[INTEGER]] + | \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#0, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#25, language_name{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected index 4ba472a701132..e5de0b72a7705 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[emp_no{f}, height{f}, hire_date{f}],false] -\_ProjectExec[[_doc{f}, hire_date{f}, height{f}]] - \_FieldExtractExec[hire_date{f}, height{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST], FieldSort[field=height{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[32] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2],false] +\_ProjectExec[[_doc{f}#3, hire_date{f}#2, height{f}#1]] + \_FieldExtractExec[hire_date{f}#2, height{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#2, direction=ASC, nulls=LAST], FieldSort[field=height{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[32] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected index 8ab7e96ac70e1..4866ac15c30c3 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, height{f}, hire_date{f}],false] +ExchangeSinkExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, hire_date{f}, height{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST], Order[height{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#3, hire_date{f}#2, height{f}#1]] +\_TopN[[Order[hire_date{f}#2,ASC,LAST], Order[height{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#1, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#2, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected index b4903131e7355..ab96def3b448c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, height{f}, hire_date{f}],false] -\_ProjectExec[[emp_no{f}, height{f}, hire_date{f}]] - \_FieldExtractExec[emp_no{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST], Order[height{f},ASC,LAST]],20[INTEGER],40] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}, height{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2],false] +\_ProjectExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2]] + \_FieldExtractExec[emp_no{f}#0]<[],[]> + \_TopNExec[[Order[hire_date{f}#2,ASC,LAST], Order[height{f}#1,ASC,LAST]],20[INTEGER],40] + \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#2, height{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected index 01e434d142dbc..64df823ba0bbf 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[hire_date{f}, emp_no{f}, height{f}]] -\_TopNExec[[Order[hire_date{f},ASC,LAST], Order[height{f},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}, height{f}, hire_date{f}],false] +ProjectExec[[hire_date{f}#0, emp_no{f}#1, height{f}#2]] +\_TopNExec[[Order[hire_date{f}#0,ASC,LAST], Order[height{f}#2,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}#1, height{f}#2, hire_date{f}#0],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, height{f}, hire_date{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST], Order[height{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#1, height{f}#2, hire_date{f}#0]] +\_TopN[[Order[hire_date{f}#0,ASC,LAST], Order[height{f}#2,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#1, first_name{f}#5, gender{f}#6, height{f}#2, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#0, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected index 79d08e098a4ac..71c01677f83a5 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[_doc{f}, hire_date{f}]] - \_FieldExtractExec[hire_date{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[_doc{f}#3, hire_date{f}#1]] + \_FieldExtractExec[hire_date{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected index 42c2f1deccb35..fc4d011c9a8fb 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, hire_date{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#3, hire_date{f}#1]] +\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected index 378271a5e3f37..4b4fc0c891ac1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] - \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> + \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected index f614767fd6b3e..92cf16635a7dc 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}, salary{f}, emp_no{f}]] -\_TopNExec[[Order[salary{f},ASC,LAST]],10[INTEGER],null] - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}, hire_date{f}, salary{f}],false] +ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] +\_TopNExec[[Order[salary{f}#1,ASC,LAST]],10[INTEGER],null] + \_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, hire_date{f}, salary{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] +\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected index 2f239d653927e..f0d827b7d0c99 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,7 +1,7 @@ -ExchangeSinkExec[[emp_no{f}, job_positions{r}, salary{f}],false] -\_ProjectExec[[emp_no{f}, job_positions{r}, salary{f}]] - \_TopNExec[[Order[salary{f},ASC,LAST]],20[INTEGER],58] - \_MvExpandExec[job_positions{f},job_positions{r}] - \_ProjectExec[[emp_no{f}, job_positions{f}, salary{f}]] - \_FieldExtractExec[emp_no{f}, job_positions{f}, salary{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[62] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2]] + \_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] + \_MvExpandExec[job_positions{f}#3,job_positions{r}#1] + \_ProjectExec[[emp_no{f}#0, job_positions{f}#3, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0, job_positions{f}#3, salary{f}#2]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#4], limit[], sort[] estimatedRowSize[62] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected index 0c801590c80b7..a9639e399dec8 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected @@ -1,3 +1,3 @@ -ExchangeSinkExec[[emp_no{f}, job_positions{r}, salary{f}],false] -\_TopNExec[[Order[salary{f},ASC,LAST]],20[INTEGER],58] - \_ExchangeSourceExec[[emp_no{f}, job_positions{r}, salary{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] +\_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] + \_ExchangeSourceExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected index 5a4be4cccf576..baf5e66932990 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected @@ -1,7 +1,7 @@ -ExchangeSinkExec[[emp_no{f}, job_positions{r}, salary{f}],false] +ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, job_positions{r}, salary{f}]] -\_TopN[[Order[salary{f},ASC,LAST]],20[INTEGER],false] - \_MvExpand[job_positions{f},job_positions{r}] - \_Project[[emp_no{f}, job_positions{f}, salary{f}]] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#0, job_positions{r}#1, salary{f}#2]] +\_TopN[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],false] + \_MvExpand[job_positions{f}#3,job_positions{r}#1] + \_Project[[emp_no{f}#0, job_positions{f}#3, salary{f}#2]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#3, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected index 0c801590c80b7..a9639e399dec8 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected @@ -1,3 +1,3 @@ -ExchangeSinkExec[[emp_no{f}, job_positions{r}, salary{f}],false] -\_TopNExec[[Order[salary{f},ASC,LAST]],20[INTEGER],58] - \_ExchangeSourceExec[[emp_no{f}, job_positions{r}, salary{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] +\_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] + \_ExchangeSourceExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected index d53c3f7c10b84..7bd205fddb3bd 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected @@ -1,8 +1,8 @@ -TopNExec[[Order[salary{f},ASC,LAST]],20[INTEGER],null] -\_ExchangeExec[[emp_no{f}, job_positions{r}, salary{f}],false] +TopNExec[[Order[salary{f}#0,ASC,LAST]],20[INTEGER],null] +\_ExchangeExec[[emp_no{f}#1, job_positions{r}#2, salary{f}#0],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, job_positions{r}, salary{f}]] -\_TopN[[Order[salary{f},ASC,LAST]],20[INTEGER],false] - \_MvExpand[job_positions{f},job_positions{r}] - \_Project[[emp_no{f}, job_positions{f}, salary{f}]] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#1, job_positions{r}#2, salary{f}#0]] +\_TopN[[Order[salary{f}#0,ASC,LAST]],20[INTEGER],false] + \_MvExpand[job_positions{f}#3,job_positions{r}#2] + \_Project[[emp_no{f}#1, job_positions{f}#3, salary{f}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#1, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#3, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#0, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected index b49e189701890..cebf3f704c28d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[emp_no{f}, height{f}],false] -\_ProjectExec[[_doc{f}, height{f}]] - \_FieldExtractExec[height{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=height{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, height{f}#1],false] +\_ProjectExec[[_doc{f}#2, height{f}#1]] + \_FieldExtractExec[height{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#2], limit[20], sort[[FieldSort[field=height{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected index bf2fa9c12991a..b2913dbdf505b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, height{f}],false] +ExchangeSinkExec[[emp_no{f}#0, height{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, height{f}]] -\_TopN[[Order[height{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#2, height{f}#1]] +\_TopN[[Order[height{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#2, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#0, first_name{f}#5, gender{f}#6, height{f}#1, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected index 787b72a5c8f72..3425364e715c1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, height{f}],false] -\_ProjectExec[[emp_no{f}, height{f}]] - \_FieldExtractExec[emp_no{f}]<[],[]> - \_TopNExec[[Order[height{f},ASC,LAST]],20[INTEGER],32] - \_ExchangeSourceExec[[_doc{f}, height{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, height{f}#1],false] +\_ProjectExec[[emp_no{f}#0, height{f}#1]] + \_FieldExtractExec[emp_no{f}#0]<[],[]> + \_TopNExec[[Order[height{f}#1,ASC,LAST]],20[INTEGER],32] + \_ExchangeSourceExec[[_doc{f}#2, height{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected index 896efe01a59ec..e659e9ce08d64 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[emp_no{f}, height{f}]] -\_TopNExec[[Order[height{f},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}, height{f}],false] +ProjectExec[[emp_no{f}#0, height{f}#1]] +\_TopNExec[[Order[height{f}#1,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}#0, height{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, height{f}]] -\_TopN[[Order[height{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#0, height{f}#1]] +\_TopN[[Order[height{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#0, first_name{f}#4, gender{f}#5, height{f}#1, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected index 7a2b16378c969..91fa3beaa5567 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected @@ -1,7 +1,7 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[_doc{f}, salary{f}, hire_date{f}]] - \_FieldExtractExec[salary{f}, hire_date{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query={ +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[_doc{f}#3, salary{f}#2, hire_date{f}#1]] + \_FieldExtractExec[salary{f}#2, hire_date{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "salary", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected index 041b22266a09e..1e90a18573c7c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, salary{f}, hire_date{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_Filter[salary{f} > 10000[INTEGER]] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#3, salary{f}#2, hire_date{f}#1]] +\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] + \_Filter[salary{f}#2 > 10000[INTEGER]] + \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected index 23b988ef09a77..178d31ccc5dc1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] - \_FieldExtractExec[emp_no{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, salary{f}, hire_date{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0]<[],[]> + \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#3, salary{f}#2, hire_date{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected index f356ac8daa272..6fc12a53e3980 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}, salary{f}, emp_no{f}]] -\_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}, hire_date{f}, salary{f}],false] +ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] +\_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, hire_date{f}, salary{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_Filter[salary{f} > 10000[INTEGER]] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] +\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] + \_Filter[salary{f}#1 > 10000[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected index 6d737b8a8eb59..8dc76dd8b28df 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[hire_date{f}, salary{f}],false] -\_ProjectExec[[_doc{f}, hire_date{f}]] - \_FieldExtractExec[hire_date{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[hire_date{f}#0, salary{f}#1],false] +\_ProjectExec[[_doc{f}#2, hire_date{f}#0]] + \_FieldExtractExec[hire_date{f}#0]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#2], limit[20], sort[[FieldSort[field=hire_date{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected index 5cc08a59070fd..070d12cb17d93 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[hire_date{f}, salary{f}],false] +ExchangeSinkExec[[hire_date{f}#0, salary{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, hire_date{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#2, hire_date{f}#0]] +\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#2, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#0, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#1, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected index 89b94a06e2096..3c81025a6c14e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[hire_date{f}, salary{f}],false] -\_ProjectExec[[hire_date{f}, salary{f}]] - \_FieldExtractExec[salary{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],32] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file +ExchangeSinkExec[[hire_date{f}#0, salary{f}#1],false] +\_ProjectExec[[hire_date{f}#0, salary{f}#1]] + \_FieldExtractExec[salary{f}#1]<[],[]> + \_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],32] + \_ExchangeSourceExec[[_doc{f}#2, hire_date{f}#0],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected index 861afa9e16c8f..d520dec0664bd 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected @@ -1,10 +1,10 @@ -ProjectExec[[avg_salary{r}, count{r}]] -\_EvalExec[[$$SUM$avg_salary$0{r$} / $$COUNT$avg_salary$1{r$} AS avg_salary]] +ProjectExec[[avg_salary{r}#0, count{r}#1]] +\_EvalExec[[$$SUM$avg_salary$0{r$}#2 / $$COUNT$avg_salary$1{r$}#3 AS avg_salary#0]] \_LimitExec[10000[INTEGER],null] - \_AggregateExec[[],[SUM(salary{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS $$SUM$avg_salary$0, COUNT(salary{f},true[BOOLEAN],PT0S[TIME_DURATION]) AS $$COUNT$avg_salary$1, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count],SINGLE,[$$SUM$avg_salary$0$sum{r}, $$SUM$avg_salary$0$seen{r}, $$COUNT$avg_salary$1$count{r}, $$COUNT$avg_salary$1$seen{r}, $$count$count{r}, $$count$seen{r}],null] - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[hire_date{f}, salary{f}],false] + \_AggregateExec[[],[SUM(salary{f}#4,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS $$SUM$avg_salary$0#2, COUNT(salary{f}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS $$COUNT$avg_salary$1#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count#1],SINGLE,[$$SUM$avg_salary$0$sum{r}#5, $$SUM$avg_salary$0$seen{r}#6, $$COUNT$avg_salary$1$count{r}#7, $$COUNT$avg_salary$1$seen{r}#8, $$count$count{r}#9, $$count$seen{r}#10],null] + \_TopNExec[[Order[hire_date{f}#11,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[hire_date{f}#11, salary{f}#4],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[hire_date{f}, salary{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[hire_date{f}#11, salary{f}#4]] +\_TopN[[Order[hire_date{f}#11,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}#12, birth_date{f}#13, emp_no{f}#14, first_name{f}#15, gender{f}#16, height{f}#17, height.float{f}#18, height.half_float{f}#19, height.scaled_float{f}#20, hire_date{f}#11, is_rehired{f}#21, job_positions{f}#22, languages{f}#23, languages.byte{f}#24, languages.long{f}#25, languages.short{f}#26, last_name{f}#27, salary{f}#4, salary_change{f}#28, salary_change.int{f}#29, salary_change.keyword{f}#30, salary_change.long{f}#31, still_hired{f}#32]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected index 86be6bee3c591..0280707cf7711 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[_doc{f}, birth_date{r} AS hire_date]] - \_EvalExec[[null[DATETIME] AS birth_date]] - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[_doc{f}#3, birth_date{r}#4 AS hire_date#1]] + \_EvalExec[[null[DATETIME] AS birth_date#4]] + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected index 42c2f1deccb35..fc4d011c9a8fb 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, hire_date{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#3, hire_date{f}#1]] +\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected index 378271a5e3f37..4b4fc0c891ac1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] - \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> + \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected index cd76be3897e14..84b502cae4e25 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[hire_date{f}, salary{f}, emp_no{f}]] -\_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}, hire_date{f}, salary{f}],false] +ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] +\_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, hire_date{f}, salary{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] +\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file From a976a8833042e5964cade910e7ac273a7b959c1c Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 3 Feb 2026 14:51:59 +0200 Subject: [PATCH 011/137] Synthetic names --- .../xpack/esql/optimizer/GoldenTestCase.java | 32 ++++++++----------- ...physical_optimization_data_driver.expected | 8 ++--- .../local_reduce_planned_data_driver.expected | 8 ++--- ...ocal_reduce_planned_reduce_driver.expected | 8 ++--- .../physical_optimization.expected | 10 +++--- ...physical_optimization_data_driver.expected | 8 ++--- .../local_reduce_planned_data_driver.expected | 8 ++--- ...ocal_reduce_planned_reduce_driver.expected | 8 ++--- .../physical_optimization.expected | 10 +++--- 9 files changed, 48 insertions(+), 52 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index e6f833bad54c6..e5e9a2ff66abd 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -28,7 +28,6 @@ import org.elasticsearch.xpack.esql.analysis.UnmappedResolution; import org.elasticsearch.xpack.esql.core.expression.FoldContext; import org.elasticsearch.xpack.esql.core.tree.Node; -import org.elasticsearch.xpack.esql.core.util.Holder; import org.elasticsearch.xpack.esql.expression.function.EsqlFunctionRegistry; import org.elasticsearch.xpack.esql.inference.InferenceResolution; import org.elasticsearch.xpack.esql.parser.EsqlParser; @@ -387,21 +386,15 @@ private static Test.TestResult createNewOutput(Path output, QueryPlan plan) t private static String normalizeNameIds(Node plan) { String full = plan.toString(Node.NodeStringFormat.FULL); - // full = normalizeSyntheticNames(full); + full = normalizeSyntheticNames(full); Matcher matcher = IDENTIFIER_PATTERN.matcher(full); StringBuilder sb = new StringBuilder(); int lastEnd = 0; - Holder counterHolder = new Holder<>(0); - Map idMap = new HashMap<>(); + var idMap = new IdMap(); while (matcher.find()) { sb.append(full, lastEnd, matcher.start()); int originalId = Integer.parseInt(matcher.group().substring(1)); // Drop the initial '#' prefix - int newId = idMap.computeIfAbsent(originalId, k -> { - int current = counterHolder.get(); - counterHolder.set(current + 1); - return current; - }); - sb.append("#").append(newId); + sb.append("#").append(idMap.getId(originalId)); lastEnd = matcher.end(); } sb.append(full, lastEnd, full.length()); @@ -416,17 +409,11 @@ private static String normalizeSyntheticNames(String full) { Matcher matcher = SYNTHETIC_PATTERN.matcher(full); StringBuilder sb = new StringBuilder(); int lastEnd = 0; - Holder runningInt = new Holder<>(0); - Map idMap = new HashMap<>(); + var idMap = new IdMap(); while (matcher.find()) { sb.append(full, lastEnd, matcher.start()); String firstSegment = matcher.group(1); - int newId = idMap.computeIfAbsent(firstSegment, k -> { - int current = runningInt.get(); - runningInt.set(current + 1); - return current; - }); - sb.append("$$").append(firstSegment).append("$").append(newId); + sb.append("$$").append(firstSegment).append("$").append(idMap.getId(firstSegment)); lastEnd = matcher.end(); } sb.append(full, lastEnd, full.length()); @@ -436,6 +423,15 @@ private static String normalizeSyntheticNames(String full) { private static final Pattern SYNTHETIC_PATTERN = Pattern.compile("\\$\\$([^$\\s]+)(\\$\\d+)+(?=[{#])"); private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("#\\d+"); + private static class IdMap { + private final Map map = new HashMap<>(); + private int counter = 0; + + public int getId(K key) { + return map.computeIfAbsent(key, k -> counter++); + } + } + private static Test.TestResult verifyExisting(Path output, QueryPlan plan) throws IOException { String testString = normalize(normalizeNameIds(plan)); if (testString.equals(normalize(Files.readString(output)))) { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected index b70e2da30d8d9..8f49d89b830ce 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[hire_date{f}#0, $$order_by$0$1{r}#1],false] -\_ProjectExec[[_doc{f}#2, $$order_by$0$1{r}#1]] - \_TopNExec[[Order[$$order_by$0$1{r}#1,ASC,LAST]],20[INTEGER],36] - \_EvalExec[[SIN(height{f}#3) * 2[INTEGER] AS $$order_by$0$1#1]] +ExchangeSinkExec[[hire_date{f}#0, $$order_by$0{r}#1],false] +\_ProjectExec[[_doc{f}#2, $$order_by$0{r}#1]] + \_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],36] + \_EvalExec[[SIN(height{f}#3) * 2[INTEGER] AS $$order_by$0#1]] \_FieldExtractExec[height{f}#3]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#2], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected index 6e7579d93480f..9ce3f748778c1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[hire_date{f}#0, $$order_by$0$1{r}#1],false] +ExchangeSinkExec[[hire_date{f}#0, $$order_by$0{r}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#2, $$order_by$0$1{r}#1]] -\_TopN[[Order[$$order_by$0$1{r}#1,ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}#3) * 2[INTEGER] AS $$order_by$0$1#1]] +Project[[_doc{f}#2, $$order_by$0{r}#1]] +\_TopN[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}#3) * 2[INTEGER] AS $$order_by$0#1]] \_EsRelation[employees][_doc{f}#2, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#3, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#0, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected index b69f8a120e20a..d2459818c5588 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[hire_date{f}#0, $$order_by$0$1{r}#1],false] -\_ProjectExec[[hire_date{f}#0, $$order_by$0$1{r}#1]] +ExchangeSinkExec[[hire_date{f}#0, $$order_by$0{r}#1],false] +\_ProjectExec[[hire_date{f}#0, $$order_by$0{r}#1]] \_FieldExtractExec[hire_date{f}#0]<[],[]> - \_TopNExec[[Order[$$order_by$0$1{r}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#2, $$order_by$0$1{r}#1],false] \ No newline at end of file + \_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#2, $$order_by$0{r}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected index 40e41a83c3210..71abdab6b07fe 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected @@ -1,8 +1,8 @@ ProjectExec[[hire_date{f}#0]] -\_TopNExec[[Order[$$order_by$0$1{r}#1,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[hire_date{f}#0, $$order_by$0$1{r}#1],false] +\_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[hire_date{f}#0, $$order_by$0{r}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[hire_date{f}#0, $$order_by$0$1{r}#1]] -\_TopN[[Order[$$order_by$0$1{r}#1,ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}#2) * 2[INTEGER] AS $$order_by$0$1#1]] +Project[[hire_date{f}#0, $$order_by$0{r}#1]] +\_TopN[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}#2) * 2[INTEGER] AS $$order_by$0#1]] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#2, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected index d7b0d2e276b29..460cbcab3451e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0$0{r}#2],false] -\_ProjectExec[[_doc{f}#3, height{f}#0, $$order_by$0$0{r}#2]] - \_TopNExec[[Order[$$order_by$0$0{r}#2,ASC,LAST]],20[INTEGER],36] - \_EvalExec[[SIN(height{f}#0) * 2[INTEGER] AS $$order_by$0$0#2]] +ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2],false] +\_ProjectExec[[_doc{f}#3, height{f}#0, $$order_by$0{r}#2]] + \_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],36] + \_EvalExec[[SIN(height{f}#0) * 2[INTEGER] AS $$order_by$0#2]] \_FieldExtractExec[height{f}#0]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected index 44d16e2751dd8..932c4834e7e80 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0$0{r}#2],false] +ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#3, height{f}#0, $$order_by$0$0{r}#2]] -\_TopN[[Order[$$order_by$0$0{r}#2,ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}#0) * 2[INTEGER] AS $$order_by$0$0#2]] +Project[[_doc{f}#3, height{f}#0, $$order_by$0{r}#2]] +\_TopN[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}#0) * 2[INTEGER] AS $$order_by$0#2]] \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#0, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected index 45f5637b6faac..88c85960c5dd2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0$0{r}#2],false] -\_ProjectExec[[height{f}#0, hire_date{f}#1, $$order_by$0$0{r}#2]] +ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2],false] +\_ProjectExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2]] \_FieldExtractExec[hire_date{f}#1]<[],[]> - \_TopNExec[[Order[$$order_by$0$0{r}#2,ASC,LAST]],20[INTEGER],44] - \_ExchangeSourceExec[[_doc{f}#3, height{f}#0, $$order_by$0$0{r}#2],false] \ No newline at end of file + \_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],44] + \_ExchangeSourceExec[[_doc{f}#3, height{f}#0, $$order_by$0{r}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected index 083b9f2af3acf..b3fbad771e03e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected @@ -1,8 +1,8 @@ ProjectExec[[hire_date{f}#0, height{f}#1]] -\_TopNExec[[Order[$$order_by$0$0{r}#2,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[height{f}#1, hire_date{f}#0, $$order_by$0$0{r}#2],false] +\_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[height{f}#1, hire_date{f}#0, $$order_by$0{r}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[height{f}#1, hire_date{f}#0, $$order_by$0$0{r}#2]] -\_TopN[[Order[$$order_by$0$0{r}#2,ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}#1) * 2[INTEGER] AS $$order_by$0$0#2]] +Project[[height{f}#1, hire_date{f}#0, $$order_by$0{r}#2]] +\_TopN[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}#1) * 2[INTEGER] AS $$order_by$0#2]] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#1, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file From 6a98ff7b13c40bb779767ec5eb81188cdf19245d Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 3 Feb 2026 15:19:41 +0200 Subject: [PATCH 012/137] Refactor --- .../xpack/esql/optimizer/GoldenTestCase.java | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index e5e9a2ff66abd..8006d3a2c7cd3 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -60,6 +60,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -380,48 +381,45 @@ private static Test.TestResult createNewOutput(Path output, QueryPlan plan) t if (output.toString().contains("extra")) { throw new IllegalStateException("Extra output files should not be created automatically:" + output); } - Files.writeString(output, normalizeNameIds(plan), StandardCharsets.UTF_8); + Files.writeString(output, toCanonicalString(plan), StandardCharsets.UTF_8); return Test.TestResult.CREATED; } - private static String normalizeNameIds(Node plan) { + private static String toCanonicalString(Node plan) { String full = plan.toString(Node.NodeStringFormat.FULL); - full = normalizeSyntheticNames(full); - Matcher matcher = IDENTIFIER_PATTERN.matcher(full); - StringBuilder sb = new StringBuilder(); - int lastEnd = 0; + return normalizeNameIds(normalizeSyntheticNames(full)); + } + + private static String normalizeNameIds(String plan) { var idMap = new IdMap(); - while (matcher.find()) { - sb.append(full, lastEnd, matcher.start()); - int originalId = Integer.parseInt(matcher.group().substring(1)); // Drop the initial '#' prefix - sb.append("#").append(idMap.getId(originalId)); - lastEnd = matcher.end(); - } - sb.append(full, lastEnd, full.length()); - return sb.toString(); + return normalizeHelper(plan, IDENTIFIER_PATTERN, s -> "#" + idMap.getId(Integer.parseInt(s))); } /** * Normalizes synthetic attribute names of the form $$something($something)* that are followed by # (node id). * Replaces them with $$firstSegment$runningInt so golden output is stable across runs. */ - private static String normalizeSyntheticNames(String full) { - Matcher matcher = SYNTHETIC_PATTERN.matcher(full); + private static String normalizeSyntheticNames(String plan) { + var idMap = new IdMap(); + return normalizeHelper(plan, SYNTHETIC_PATTERN, s -> "$$" + s + "$" + idMap.getId(s)); + } + + private static String normalizeHelper(String s, Pattern p, Function replacer) { + Matcher matcher = p.matcher(s); StringBuilder sb = new StringBuilder(); int lastEnd = 0; - var idMap = new IdMap(); while (matcher.find()) { - sb.append(full, lastEnd, matcher.start()); - String firstSegment = matcher.group(1); - sb.append("$$").append(firstSegment).append("$").append(idMap.getId(firstSegment)); + sb.append(s, lastEnd, matcher.start()); + sb.append(replacer.apply(matcher.group(1))); lastEnd = matcher.end(); } - sb.append(full, lastEnd, full.length()); + sb.append(s, lastEnd, s.length()); return sb.toString(); + } private static final Pattern SYNTHETIC_PATTERN = Pattern.compile("\\$\\$([^$\\s]+)(\\$\\d+)+(?=[{#])"); - private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("#\\d+"); + private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("#(\\d+)"); private static class IdMap { private final Map map = new HashMap<>(); @@ -433,7 +431,7 @@ public int getId(K key) { } private static Test.TestResult verifyExisting(Path output, QueryPlan plan) throws IOException { - String testString = normalize(normalizeNameIds(plan)); + String testString = normalize(toCanonicalString(plan)); if (testString.equals(normalize(Files.readString(output)))) { if (System.getProperty("golden.cleanactual") != null) { Path path = actualPath(output); From dd3ef6ba821816e9ca9a2b9137328f5de4735468 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 3 Feb 2026 17:05:04 +0200 Subject: [PATCH 013/137] Golden test start --- .../analysis/AnalyzerUnmappedGoldenTests.java | 295 ++++++++++++++++++ .../xpack/esql/optimizer/GoldenTestCase.java | 12 +- 2 files changed, 301 insertions(+), 6 deletions(-) create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java new file mode 100644 index 0000000000000..9db97289ae7ae --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -0,0 +1,295 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.analysis; + +import org.elasticsearch.xpack.esql.action.EsqlCapabilities; +import org.elasticsearch.xpack.esql.optimizer.GoldenTestCase; + +import java.util.EnumSet; + +import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning; + +/** + * Golden tests for analyzer behavior with unmapped fields using SET unmapped_fields="nullify". + * These tests verify that unmapped fields are properly handled by converting them to null literals. + */ +public class AnalyzerUnmappedGoldenTests extends GoldenTestCase { + private static final EnumSet STAGES = EnumSet.of(Stage.ANALYSIS); + + public void testKeep() throws Exception { + runTests(""" + FROM test + | KEEP does_not_exist_field + """); + } + + public void testKeepRepeated() throws Exception { + runTests(""" + FROM test + | KEEP does_not_exist_field, does_not_exist_field + """); + } + + public void testKeepAndMatchingStar() throws Exception { + runTests(""" + FROM test + | KEEP emp_*, does_not_exist_field + """); + } + + public void testEvalAndKeep() throws Exception { + runTests(""" + FROM test + | EVAL x = does_not_exist_field1::INTEGER + 42 + | KEEP does_not_exist_field1, does_not_exist_field2 + """); + } + + public void testEvalAfterKeepStar() throws Exception { + runTests(""" + FROM test + | KEEP * + | EVAL x = emp_no + 1 + | EVAL y = does_not_exist_field + 2 + """); + } + + public void testEvalAfterMatchingKeepWithWildcard() throws Exception { + runTests(""" + FROM test + | KEEP emp_no, * + | EVAL x = emp_no + 1 + | EVAL y = emp_does_not_exist_field + 2 + """); + } + + public void testDrop() throws Exception { + runTests(""" + FROM test + | DROP does_not_exist_field, emp_no + """); + } + + public void testDropAndMatchingStar() throws Exception { + runTests(""" + FROM test + | DROP emp_*, does_not_exist_field + """); + } + + public void testRename() throws Exception { + runTests(""" + FROM test + | RENAME does_not_exist_field AS now_it_does, emp_no AS employee_number + """); + } + + public void testRenameRepeated() throws Exception { + runTests(""" + FROM test + | RENAME does_not_exist_field AS now_it_does, neither_does_this AS now_it_does, emp_no AS employee_number + """); + } + + public void testRenameEval() throws Exception { + runTests(""" + FROM test + | RENAME emp_no AS employee_number + | EVAL x = does_not_exist + 1 + """); + } + + public void testEval() throws Exception { + runTests(""" + FROM test + | EVAL x = does_not_exist_field + 1 + """); + } + + public void testMultipleEval() throws Exception { + runTests(""" + FROM test + | EVAL a = 1 + | EVAL x = a + b + | EVAL y = b + c + """); + } + + public void testEvalCast() throws Exception { + runTests(""" + FROM test + | EVAL x = does_not_exist_field::LONG + """); + } + + public void testEvalCastInPlace() throws Exception { + runTests(""" + FROM test + | EVAL does_not_exist_field::LONG + """); + } + + public void testEvalReplace() throws Exception { + runTests(""" + FROM test + | EVAL x = does_not_exist_field + 1 + | EVAL does_not_exist_field = 42 + """); + } + + public void testKeepThenEval() throws Exception { + runTests(""" + FROM test + | KEEP does_not_exist_field + | EVAL does_not_exist_field = 42 + """); + } + + public void testStatsCount() throws Exception { + runTests(""" + FROM test + | STATS cnt = COUNT(does_not_exist_field) + """); + } + + public void testStatsBy() throws Exception { + runTests(""" + FROM test + | STATS BY does_not_exist_field + """); + } + + public void testStatsSumBy() throws Exception { + runTests(""" + FROM test + | STATS s = SUM(does_not_exist1) BY does_not_exist2 + """); + } + + public void testStatsSumByMultiple() throws Exception { + runTests(""" + FROM test + | STATS s = SUM(does_not_exist1) + d2 BY d2 = does_not_exist2, emp_no + """); + } + + public void testStatsSumByComplex() throws Exception { + runTests(""" + FROM test + | STATS sum = SUM(does_not_exist1) + s0 + s1 BY s0 = does_not_exist2 + does_not_exist3, s1 = emp_no + """); + } + + public void testStatsMultiple() throws Exception { + runTests(""" + FROM test + | STATS s = SUM(does_not_exist1), c = COUNT(*) BY does_not_exist2, emp_no + """); + } + + public void testInlineStats() throws Exception { + runTests(""" + FROM test + | INLINE STATS s = SUM(does_not_exist1), c = COUNT(*) BY does_not_exist2, emp_no + """); + } + + public void testWhere() throws Exception { + runTests(""" + FROM test + | WHERE does_not_exist::LONG > 0 + """); + } + + public void testWhereOr() throws Exception { + runTests(""" + FROM test + | WHERE does_not_exist::LONG > 0 OR emp_no > 0 + """); + } + + public void testWhereComplex() throws Exception { + runTests(""" + FROM test + | WHERE does_not_exist1::LONG > 0 OR emp_no > 0 AND does_not_exist2::LONG < 100 + """); + } + + public void testStatsCountWhere() throws Exception { + runTests(""" + FROM test + | STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 + """); + } + + public void testStatsMultipleCountWhere() throws Exception { + runTests(""" + FROM test + | STATS c1 = COUNT(*) WHERE does_not_exist1::LONG > 0 OR emp_no > 0 OR does_not_exist2::LONG < 100, + c2 = COUNT(*) WHERE does_not_exist3 IS NULL + """); + } + + public void testSort() throws Exception { + runTests(""" + FROM test + | SORT does_not_exist ASC + """); + } + + public void testSortExpression() throws Exception { + runTests(""" + FROM test + | SORT does_not_exist::LONG + 1 + """); + } + + public void testSortMultiple() throws Exception { + runTests(""" + FROM test + | SORT does_not_exist1::LONG + 1, does_not_exist2 DESC, emp_no ASC + """); + } + + public void testMvExpand() throws Exception { + runTests(""" + FROM test + | MV_EXPAND does_not_exist + """); + } + + public void testRow() throws Exception { + runTests(""" + ROW x = 1 + | EVAL y = does_not_exist_field1::INTEGER + x + | KEEP *, does_not_exist_field2 + """); + } + + @Override + protected java.util.List filteredWarnings() { + return withDefaultLimitWarning(super.filteredWarnings()); + } + + private static String setUnmappedNullify(String query) { + return "SET unmapped_fields=\"nullify\"; " + query; + } + + private static String setUnmappedLoad(String query) { + return "SET unmapped_fields=\"load\"; " + query; + } + + private void runTests(String query) { + if (EsqlCapabilities.Cap.OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW.isEnabled()) { + builder(setUnmappedNullify(query)).nestedPath("nullify").stages(STAGES).run(); + } + if (EsqlCapabilities.Cap.OPTIONAL_FIELDS.isEnabled()) { + builder(setUnmappedLoad(query)).nestedPath("load").stages(STAGES).run(); + } + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 8006d3a2c7cd3..6c343827b3cbb 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -391,8 +391,8 @@ private static String toCanonicalString(Node plan) { } private static String normalizeNameIds(String plan) { - var idMap = new IdMap(); - return normalizeHelper(plan, IDENTIFIER_PATTERN, s -> "#" + idMap.getId(Integer.parseInt(s))); + var idMap = new IdMap(); + return normalizeHelper(plan, IDENTIFIER_PATTERN, s -> "#" + idMap.getId(s)); } /** @@ -400,7 +400,7 @@ private static String normalizeNameIds(String plan) { * Replaces them with $$firstSegment$runningInt so golden output is stable across runs. */ private static String normalizeSyntheticNames(String plan) { - var idMap = new IdMap(); + var idMap = new IdMap(); return normalizeHelper(plan, SYNTHETIC_PATTERN, s -> "$$" + s + "$" + idMap.getId(s)); } @@ -421,11 +421,11 @@ private static String normalizeHelper(String s, Pattern p, Function { - private final Map map = new HashMap<>(); + private static class IdMap { + private final Map map = new HashMap<>(); private int counter = 0; - public int getId(K key) { + public int getId(String key) { return map.computeIfAbsent(key, k -> counter++); } } From e0b20db9793abcb86034aec98dfa263273a17a5a Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 3 Feb 2026 17:25:28 +0200 Subject: [PATCH 014/137] Fix set issue --- .../analysis/AnalyzerUnmappedGoldenTests.java | 102 ++++++++---------- .../xpack/esql/optimizer/GoldenTestCase.java | 11 +- .../testDrop/load/analysis.expected | 3 + .../testDrop/nullify/analysis.expected | 4 + .../testDrop/query.esql | 2 + .../load/analysis.expected | 3 + .../nullify/analysis.expected | 4 + .../testDropAndMatchingStar/query.esql | 2 + .../testEval/load/analysis.expected | 3 + .../testEval/nullify/analysis.expected | 4 + .../testEval/query.esql | 2 + .../load/analysis.expected | 5 + .../nullify/analysis.expected | 6 ++ .../testEvalAfterKeepStar/query.esql | 4 + .../load/analysis.expected | 5 + .../nullify/analysis.expected | 6 ++ .../query.esql | 4 + .../testEvalAndKeep/load/analysis.expected | 4 + .../testEvalAndKeep/nullify/analysis.expected | 5 + .../testEvalAndKeep/query.esql | 3 + .../testEvalCast/load/analysis.expected | 3 + .../testEvalCast/nullify/analysis.expected | 4 + .../testEvalCast/query.esql | 2 + .../load/analysis.expected | 3 + .../nullify/analysis.expected | 4 + .../testEvalCastInPlace/query.esql | 2 + .../testEvalReplace/load/analysis.expected | 4 + .../testEvalReplace/nullify/analysis.expected | 5 + .../testEvalReplace/query.esql | 3 + .../testInlineStats/load/analysis.expected | 4 + .../testInlineStats/nullify/analysis.expected | 5 + .../testInlineStats/query.esql | 2 + .../testKeep/load/analysis.expected | 3 + .../testKeep/nullify/analysis.expected | 4 + .../testKeep/query.esql | 2 + .../load/analysis.expected | 3 + .../nullify/analysis.expected | 4 + .../testKeepAndMatchingStar/query.esql | 2 + .../testKeepRepeated/load/analysis.expected | 3 + .../nullify/analysis.expected | 4 + .../testKeepRepeated/query.esql | 2 + .../testKeepThenEval/load/analysis.expected | 4 + .../nullify/analysis.expected | 5 + .../testKeepThenEval/query.esql | 3 + .../testMultipleEval/load/analysis.expected | 5 + .../nullify/analysis.expected | 5 + .../testMultipleEval/query.esql | 4 + .../testMvExpand/load/analysis.expected | 3 + .../testMvExpand/nullify/analysis.expected | 4 + .../testMvExpand/query.esql | 2 + .../testRename/load/analysis.expected | 3 + .../testRename/nullify/analysis.expected | 4 + .../testRename/query.esql | 2 + .../testRenameEval/load/analysis.expected | 4 + .../testRenameEval/nullify/analysis.expected | 5 + .../testRenameEval/query.esql | 3 + .../testRenameRepeated/load/analysis.expected | 3 + .../nullify/analysis.expected | 4 + .../testRenameRepeated/query.esql | 2 + .../testSort/load/analysis.expected | 3 + .../testSort/nullify/analysis.expected | 4 + .../testSort/query.esql | 2 + .../testSortExpression/load/analysis.expected | 3 + .../nullify/analysis.expected | 4 + .../testSortExpression/query.esql | 2 + .../testSortMultiple/load/analysis.expected | 3 + .../nullify/analysis.expected | 4 + .../testSortMultiple/query.esql | 2 + .../testStatsBy/load/analysis.expected | 3 + .../testStatsBy/nullify/analysis.expected | 4 + .../testStatsBy/query.esql | 2 + .../testStatsCount/load/analysis.expected | 3 + .../testStatsCount/nullify/analysis.expected | 4 + .../testStatsCount/query.esql | 2 + .../load/analysis.expected | 3 + .../nullify/analysis.expected | 4 + .../testStatsCountWhere/query.esql | 2 + .../testStatsMultiple/load/analysis.expected | 3 + .../nullify/analysis.expected | 4 + .../testStatsMultiple/query.esql | 2 + .../load/analysis.expected | 4 + .../nullify/analysis.expected | 5 + .../testStatsMultipleCountWhere/query.esql | 3 + .../testStatsSumBy/load/analysis.expected | 3 + .../testStatsSumBy/nullify/analysis.expected | 4 + .../testStatsSumBy/query.esql | 2 + .../load/analysis.expected | 3 + .../nullify/analysis.expected | 4 + .../testStatsSumByComplex/query.esql | 2 + .../load/analysis.expected | 3 + .../nullify/analysis.expected | 4 + .../testStatsSumByMultiple/query.esql | 2 + .../testWhere/load/analysis.expected | 3 + .../testWhere/nullify/analysis.expected | 4 + .../testWhere/query.esql | 2 + .../testWhereComplex/load/analysis.expected | 3 + .../nullify/analysis.expected | 4 + .../testWhereComplex/query.esql | 2 + .../testWhereOr/load/analysis.expected | 3 + .../testWhereOr/nullify/analysis.expected | 4 + .../testWhereOr/query.esql | 2 + 101 files changed, 385 insertions(+), 59 deletions(-) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/query.esql diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java index 9db97289ae7ae..e1de3ba5bf151 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -15,36 +15,36 @@ import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning; /** - * Golden tests for analyzer behavior with unmapped fields using SET unmapped_fields="nullify". - * These tests verify that unmapped fields are properly handled by converting them to null literals. + * Golden tests for analyzer behavior with unmapped fields using SET unmapped_fields="nullify" and "load". + * These tests verify that unmapped fields are properly handled. */ public class AnalyzerUnmappedGoldenTests extends GoldenTestCase { private static final EnumSet STAGES = EnumSet.of(Stage.ANALYSIS); public void testKeep() throws Exception { runTests(""" - FROM test + FROM employees | KEEP does_not_exist_field """); } public void testKeepRepeated() throws Exception { runTests(""" - FROM test + FROM employees | KEEP does_not_exist_field, does_not_exist_field """); } public void testKeepAndMatchingStar() throws Exception { runTests(""" - FROM test + FROM employees | KEEP emp_*, does_not_exist_field """); } public void testEvalAndKeep() throws Exception { runTests(""" - FROM test + FROM employees | EVAL x = does_not_exist_field1::INTEGER + 42 | KEEP does_not_exist_field1, does_not_exist_field2 """); @@ -52,99 +52,99 @@ public void testEvalAndKeep() throws Exception { public void testEvalAfterKeepStar() throws Exception { runTests(""" - FROM test + FROM employees | KEEP * | EVAL x = emp_no + 1 - | EVAL y = does_not_exist_field + 2 + | EVAL y = does_not_exist_field::DOUBLE + 2 """); } public void testEvalAfterMatchingKeepWithWildcard() throws Exception { runTests(""" - FROM test + FROM employees | KEEP emp_no, * | EVAL x = emp_no + 1 - | EVAL y = emp_does_not_exist_field + 2 + | EVAL y = emp_does_not_exist_field::DOUBLE + 2 """); } public void testDrop() throws Exception { runTests(""" - FROM test + FROM employees | DROP does_not_exist_field, emp_no """); } public void testDropAndMatchingStar() throws Exception { runTests(""" - FROM test + FROM employees | DROP emp_*, does_not_exist_field """); } public void testRename() throws Exception { runTests(""" - FROM test + FROM employees | RENAME does_not_exist_field AS now_it_does, emp_no AS employee_number """); } public void testRenameRepeated() throws Exception { runTests(""" - FROM test + FROM employees | RENAME does_not_exist_field AS now_it_does, neither_does_this AS now_it_does, emp_no AS employee_number """); } public void testRenameEval() throws Exception { runTests(""" - FROM test + FROM employees | RENAME emp_no AS employee_number - | EVAL x = does_not_exist + 1 + | EVAL x = does_not_exist::DOUBLE + 1 """); } public void testEval() throws Exception { runTests(""" - FROM test - | EVAL x = does_not_exist_field + 1 + FROM employees + | EVAL x = does_not_exist_field::DOUBLE + 1 """); } public void testMultipleEval() throws Exception { runTests(""" - FROM test + FROM employees | EVAL a = 1 - | EVAL x = a + b - | EVAL y = b + c + | EVAL x = a + b::DOUBLE + | EVAL y = b::DOUBLE + c::DOUBLE """); } public void testEvalCast() throws Exception { runTests(""" - FROM test + FROM employees | EVAL x = does_not_exist_field::LONG """); } public void testEvalCastInPlace() throws Exception { runTests(""" - FROM test + FROM employees | EVAL does_not_exist_field::LONG """); } public void testEvalReplace() throws Exception { runTests(""" - FROM test - | EVAL x = does_not_exist_field + 1 + FROM employees + | EVAL x = does_not_exist_field::DOUBLE + 1 | EVAL does_not_exist_field = 42 """); } public void testKeepThenEval() throws Exception { runTests(""" - FROM test + FROM employees | KEEP does_not_exist_field | EVAL does_not_exist_field = 42 """); @@ -152,84 +152,84 @@ public void testKeepThenEval() throws Exception { public void testStatsCount() throws Exception { runTests(""" - FROM test + FROM employees | STATS cnt = COUNT(does_not_exist_field) """); } public void testStatsBy() throws Exception { runTests(""" - FROM test + FROM employees | STATS BY does_not_exist_field """); } public void testStatsSumBy() throws Exception { runTests(""" - FROM test - | STATS s = SUM(does_not_exist1) BY does_not_exist2 + FROM employees + | STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 """); } public void testStatsSumByMultiple() throws Exception { runTests(""" - FROM test - | STATS s = SUM(does_not_exist1) + d2 BY d2 = does_not_exist2, emp_no + FROM employees + | STATS s = SUM(does_not_exist1::DOUBLE) + d2 BY d2 = does_not_exist2::DOUBLE, emp_no """); } public void testStatsSumByComplex() throws Exception { runTests(""" - FROM test - | STATS sum = SUM(does_not_exist1) + s0 + s1 BY s0 = does_not_exist2 + does_not_exist3, s1 = emp_no + FROM employees + | STATS sum = SUM(does_not_exist1::DOUBLE) + s0 + s1 BY s0 = does_not_exist2::DOUBLE + does_not_exist3::DOUBLE, s1 = emp_no """); } public void testStatsMultiple() throws Exception { runTests(""" - FROM test - | STATS s = SUM(does_not_exist1), c = COUNT(*) BY does_not_exist2, emp_no + FROM employees + | STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no """); } public void testInlineStats() throws Exception { runTests(""" - FROM test - | INLINE STATS s = SUM(does_not_exist1), c = COUNT(*) BY does_not_exist2, emp_no + FROM employees + | INLINE STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no """); } public void testWhere() throws Exception { runTests(""" - FROM test + FROM employees | WHERE does_not_exist::LONG > 0 """); } public void testWhereOr() throws Exception { runTests(""" - FROM test + FROM employees | WHERE does_not_exist::LONG > 0 OR emp_no > 0 """); } public void testWhereComplex() throws Exception { runTests(""" - FROM test + FROM employees | WHERE does_not_exist1::LONG > 0 OR emp_no > 0 AND does_not_exist2::LONG < 100 """); } public void testStatsCountWhere() throws Exception { runTests(""" - FROM test + FROM employees | STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 """); } public void testStatsMultipleCountWhere() throws Exception { runTests(""" - FROM test + FROM employees | STATS c1 = COUNT(*) WHERE does_not_exist1::LONG > 0 OR emp_no > 0 OR does_not_exist2::LONG < 100, c2 = COUNT(*) WHERE does_not_exist3 IS NULL """); @@ -237,40 +237,32 @@ public void testStatsMultipleCountWhere() throws Exception { public void testSort() throws Exception { runTests(""" - FROM test + FROM employees | SORT does_not_exist ASC """); } public void testSortExpression() throws Exception { runTests(""" - FROM test + FROM employees | SORT does_not_exist::LONG + 1 """); } public void testSortMultiple() throws Exception { runTests(""" - FROM test + FROM employees | SORT does_not_exist1::LONG + 1, does_not_exist2 DESC, emp_no ASC """); } public void testMvExpand() throws Exception { runTests(""" - FROM test + FROM employees | MV_EXPAND does_not_exist """); } - public void testRow() throws Exception { - runTests(""" - ROW x = 1 - | EVAL y = does_not_exist_field1::INTEGER + x - | KEEP *, does_not_exist_field2 - """); - } - @Override protected java.util.List filteredWarnings() { return withDefaultLimitWarning(super.filteredWarnings()); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 6c343827b3cbb..5a3390f4d530c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -68,6 +68,7 @@ import static org.elasticsearch.xpack.esql.EsqlTestUtils.TEST_VERIFIER; import static org.elasticsearch.xpack.esql.EsqlTestUtils.randomMinimumVersion; import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning; +import static org.elasticsearch.xpack.esql.plan.QuerySettings.UNMAPPED_FIELDS; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.defaultLookupResolution; /** See GoldenTestsReadme.md for more information about these tests. */ @@ -200,24 +201,25 @@ private void doTest() { } private List> doTests() throws IOException { - LogicalPlan parsedStatement = EsqlParser.INSTANCE.parseQuery(esqlQuery); + var statement = EsqlParser.INSTANCE.createStatement(esqlQuery); + var parsedPlan = statement.plan(); Files.createDirectories(PathUtils.get(basePath.toString(), testName)); Files.writeString(PathUtils.get(basePath.toString(), testName, "query.esql"), esqlQuery); var analyzer = new Analyzer( new AnalyzerContext( EsqlTestUtils.TEST_CFG, new EsqlFunctionRegistry(), - CsvTests.loadIndexResolution(CsvTests.testDatasets(parsedStatement)), + CsvTests.loadIndexResolution(CsvTests.testDatasets(parsedPlan)), defaultLookupResolution(), new EnrichResolution(), InferenceResolution.EMPTY, transportVersion, - UnmappedResolution.FAIL + statement.setting(UNMAPPED_FIELDS) ), TEST_VERIFIER ); List> result = new ArrayList<>(); - var analyzed = analyzer.analyze(parsedStatement); + var analyzed = analyzer.analyze(parsedPlan); if (stages.contains(Stage.ANALYSIS)) { result.add(Tuple.tuple(Stage.ANALYSIS, verifyOrWrite(analyzed, Stage.ANALYSIS))); } @@ -381,6 +383,7 @@ private static Test.TestResult createNewOutput(Path output, QueryPlan plan) t if (output.toString().contains("extra")) { throw new IllegalStateException("Extra output files should not be created automatically:" + output); } + Files.createDirectories(output.getParent()); Files.writeString(output, toCanonicalString(plan), StandardCharsets.UTF_8); return Test.TestResult.CREATED; } diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected new file mode 100644 index 0000000000000..f5ab73414c471 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#22, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21, does_not_exist_field{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected new file mode 100644 index 0000000000000..09d5818b5d458 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21]] + \_Eval[[null[NULL] AS does_not_exist_field#22]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#23, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/query.esql new file mode 100644 index 0000000000000..4651e798553a5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| DROP does_not_exist_field, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected new file mode 100644 index 0000000000000..f5ab73414c471 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#22, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21, does_not_exist_field{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected new file mode 100644 index 0000000000000..09d5818b5d458 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21]] + \_Eval[[null[NULL] AS does_not_exist_field#22]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#23, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/query.esql new file mode 100644 index 0000000000000..0b9aa5a1c9b86 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| DROP emp_*, does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/load/analysis.expected new file mode 100644 index 0000000000000..26eeae08a3eb3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(does_not_exist_field{f}#0) + 1[INTEGER] AS x#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/analysis.expected new file mode 100644 index 0000000000000..58562d7c829d1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(does_not_exist_field{r}#0) + 1[INTEGER] AS x#1]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/query.esql new file mode 100644 index 0000000000000..f4ebacdf1a902 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| EVAL x = does_not_exist_field::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/analysis.expected new file mode 100644 index 0000000000000..fffeff38bda8f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(does_not_exist_field{f}#0) + 2[INTEGER] AS y#1]] + \_Eval[[emp_no{f}#2 + 1[INTEGER] AS x#3]] + \_Project[[avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{f}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/analysis.expected new file mode 100644 index 0000000000000..8a7ed2a845200 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/analysis.expected @@ -0,0 +1,6 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(does_not_exist_field{r}#0) + 2[INTEGER] AS y#1]] + \_Eval[[emp_no{f}#2 + 1[INTEGER] AS x#3]] + \_Project[[avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{r}#0]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/query.esql new file mode 100644 index 0000000000000..dcd26bdd54bf4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees +| KEEP * +| EVAL x = emp_no + 1 +| EVAL y = does_not_exist_field::DOUBLE + 2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/analysis.expected new file mode 100644 index 0000000000000..985d0ddb1a1f7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(emp_does_not_exist_field{f}#0) + 2[INTEGER] AS y#1]] + \_Eval[[emp_no{f}#2 + 1[INTEGER] AS x#3]] + \_Project[[emp_no{f}#2, avg_worked_seconds{f}#4, birth_date{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, emp_does_not_exist_field{f}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, emp_does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/analysis.expected new file mode 100644 index 0000000000000..c85c64472a028 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/analysis.expected @@ -0,0 +1,6 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(emp_does_not_exist_field{r}#0) + 2[INTEGER] AS y#1]] + \_Eval[[emp_no{f}#2 + 1[INTEGER] AS x#3]] + \_Project[[emp_no{f}#2, avg_worked_seconds{f}#4, birth_date{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, emp_does_not_exist_field{r}#0]] + \_Eval[[null[NULL] AS emp_does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/query.esql new file mode 100644 index 0000000000000..598a0d6552097 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees +| KEEP emp_no, * +| EVAL x = emp_no + 1 +| EVAL y = emp_does_not_exist_field::DOUBLE + 2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/analysis.expected new file mode 100644 index 0000000000000..5577ec2723da6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[does_not_exist_field1{f}#0, does_not_exist_field2{f}#1]] + \_Eval[[TOINTEGER(does_not_exist_field1{f}#0) + 42[INTEGER] AS x#2]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field1{f}#0, does_not_exist_field2{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/analysis.expected new file mode 100644 index 0000000000000..93470d82bb0f9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Project[[does_not_exist_field1{r}#0, does_not_exist_field2{r}#1]] + \_Eval[[TOINTEGER(does_not_exist_field1{r}#0) + 42[INTEGER] AS x#2]] + \_Eval[[null[NULL] AS does_not_exist_field1#0, null[NULL] AS does_not_exist_field2#1]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/query.esql new file mode 100644 index 0000000000000..2a2c4f3dea742 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| EVAL x = does_not_exist_field1::INTEGER + 42 +| KEEP does_not_exist_field1, does_not_exist_field2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected new file mode 100644 index 0000000000000..11402fc799020 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TOLONG(does_not_exist_field{f}#0) AS x#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/analysis.expected new file mode 100644 index 0000000000000..94776e53044a1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TOLONG(does_not_exist_field{r}#0) AS x#1]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/query.esql new file mode 100644 index 0000000000000..f26a0fbca818e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| EVAL x = does_not_exist_field::LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected new file mode 100644 index 0000000000000..81f2f5801c839 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TOLONG(does_not_exist_field{f}#0) AS does_not_exist_field::LONG#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/analysis.expected new file mode 100644 index 0000000000000..8b534e63aaf3c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TOLONG(does_not_exist_field{r}#0) AS does_not_exist_field::LONG#1]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/query.esql new file mode 100644 index 0000000000000..fde7a9a40d5e3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| EVAL does_not_exist_field::LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected new file mode 100644 index 0000000000000..ffb2c79dd6cd0 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[42[INTEGER] AS does_not_exist_field#0]] + \_Eval[[TODOUBLE(does_not_exist_field{f}#1) + 1[INTEGER] AS x#2]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected new file mode 100644 index 0000000000000..5ce8713e6a882 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[42[INTEGER] AS does_not_exist_field#0]] + \_Eval[[TODOUBLE(does_not_exist_field{r}#1) + 1[INTEGER] AS x#2]] + \_Eval[[null[NULL] AS does_not_exist_field#1]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/query.esql new file mode 100644 index 0000000000000..826ae0ac8f745 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| EVAL x = does_not_exist_field::DOUBLE + 1 +| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected new file mode 100644 index 0000000000000..36814b4fcb812 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_InlineStats[] + \_Aggregate[[does_not_exist2{f}#0, emp_no{f}#1],[SUM(TODOUBLE(does_not_exist1{f}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{f}#0, emp_no{f}#1]] + \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#1, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26, does_not_exist2{f}#0, does_not_exist1{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected new file mode 100644 index 0000000000000..5f2ab1697cd95 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_InlineStats[] + \_Aggregate[[does_not_exist2{r}#0, emp_no{f}#1],[SUM(TODOUBLE(does_not_exist1{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{r}#0, emp_no{f}#1]] + \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist1#2]] + \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#1, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/query.esql new file mode 100644 index 0000000000000..8c7146b6bb792 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| INLINE STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected new file mode 100644 index 0000000000000..b0d320e2b8ee8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[does_not_exist_field{f}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/analysis.expected new file mode 100644 index 0000000000000..4cc092c3f4aee --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[does_not_exist_field{r}#0]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/query.esql new file mode 100644 index 0000000000000..85b4cb1847fc2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| KEEP does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/analysis.expected new file mode 100644 index 0000000000000..872c7642ff1f5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{f}#0, does_not_exist_field{f}#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#0, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/analysis.expected new file mode 100644 index 0000000000000..cc66e19745707 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{f}#0, does_not_exist_field{r}#1]] + \_Eval[[null[NULL] AS does_not_exist_field#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#0, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/query.esql new file mode 100644 index 0000000000000..5c1bb707e111a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| KEEP emp_*, does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/analysis.expected new file mode 100644 index 0000000000000..b0d320e2b8ee8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[does_not_exist_field{f}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/analysis.expected new file mode 100644 index 0000000000000..4cc092c3f4aee --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[does_not_exist_field{r}#0]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/query.esql new file mode 100644 index 0000000000000..ffc9a50988725 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| KEEP does_not_exist_field, does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected new file mode 100644 index 0000000000000..c6a21f8491422 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[42[INTEGER] AS does_not_exist_field#0]] + \_Project[[does_not_exist_field{f}#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected new file mode 100644 index 0000000000000..f95ae9f74e6dc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[42[INTEGER] AS does_not_exist_field#0]] + \_Project[[does_not_exist_field{r}#1]] + \_Eval[[null[NULL] AS does_not_exist_field#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/query.esql new file mode 100644 index 0000000000000..945f0e290ca38 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| KEEP does_not_exist_field +| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/load/analysis.expected new file mode 100644 index 0000000000000..9b8968ae63fd7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/load/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(b{f}#0) + TODOUBLE(c{f}#1) AS y#2]] + \_Eval[[a{r}#3 + TODOUBLE(b{f}#0) AS x#4]] + \_Eval[[1[INTEGER] AS a#3]] + \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#7, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27, b{f}#0, c{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/analysis.expected new file mode 100644 index 0000000000000..db17e201ae307 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(b{r}#0) + TODOUBLE(c{r}#1) AS y#2]] + \_Eval[[a{r}#3 + TODOUBLE(b{r}#0) AS x#4]] + \_Eval[[1[INTEGER] AS a#3, null[NULL] AS b#0, null[NULL] AS c#1]] + \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#7, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/query.esql new file mode 100644 index 0000000000000..78c3271ba9d3c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees +| EVAL a = 1 +| EVAL x = a + b::DOUBLE +| EVAL y = b::DOUBLE + c::DOUBLE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/analysis.expected new file mode 100644 index 0000000000000..431d39d786c87 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_MvExpand[does_not_exist{f}#0,does_not_exist{r}#1] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/analysis.expected new file mode 100644 index 0000000000000..2720ef7cf3a24 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_MvExpand[does_not_exist{r}#0,does_not_exist{r}#1] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/query.esql new file mode 100644 index 0000000000000..470cc59438c6c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| MV_EXPAND does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/analysis.expected new file mode 100644 index 0000000000000..d593728177af5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2 AS employee_number#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#24 AS now_it_does#25]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/analysis.expected new file mode 100644 index 0000000000000..8dd19dd1a11b8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2 AS employee_number#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{r}#24 AS now_it_does#25]] + \_Eval[[null[NULL] AS does_not_exist_field#24]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/query.esql new file mode 100644 index 0000000000000..319f90371ed9c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| RENAME does_not_exist_field AS now_it_does, emp_no AS employee_number diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected new file mode 100644 index 0000000000000..a802df25ed62b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(does_not_exist{f}#0) + 1[INTEGER] AS x#1]] + \_Project[[avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4 AS employee_number#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected new file mode 100644 index 0000000000000..f96459400cd9a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(does_not_exist{r}#0) + 1[INTEGER] AS x#1]] + \_Project[[avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4 AS employee_number#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{r}#0]] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/query.esql new file mode 100644 index 0000000000000..15a3d0131d523 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| RENAME emp_no AS employee_number +| EVAL x = does_not_exist::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected new file mode 100644 index 0000000000000..0cc4d05a2041e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2 AS employee_number#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, neither_does_this{f}#24 AS now_it_does#25]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#26, neither_does_this{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected new file mode 100644 index 0000000000000..7507e4ff3fa4e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2 AS employee_number#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, neither_does_this{r}#24 AS now_it_does#25]] + \_Eval[[null[NULL] AS does_not_exist_field#26, null[NULL] AS neither_does_this#24]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/query.esql new file mode 100644 index 0000000000000..efad9ee315214 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| RENAME does_not_exist_field AS now_it_does, neither_does_this AS now_it_does, emp_no AS employee_number diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/analysis.expected new file mode 100644 index 0000000000000..441f28eeb2c20 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[does_not_exist{f}#0,ASC,LAST]]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/analysis.expected new file mode 100644 index 0000000000000..df3459bd98905 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[does_not_exist{r}#0,ASC,LAST]]] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/query.esql new file mode 100644 index 0000000000000..6f307e4be48c6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| SORT does_not_exist ASC diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/load/analysis.expected new file mode 100644 index 0000000000000..194c11cb2dd74 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[TOLONG(does_not_exist{f}#0) + 1[INTEGER],ASC,LAST]]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/analysis.expected new file mode 100644 index 0000000000000..09bb15a967666 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[TOLONG(does_not_exist{r}#0) + 1[INTEGER],ASC,LAST]]] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/query.esql new file mode 100644 index 0000000000000..0f20bd09a4191 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| SORT does_not_exist::LONG + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected new file mode 100644 index 0000000000000..663bca06a5e21 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[TOLONG(does_not_exist1{f}#0) + 1[INTEGER],ASC,LAST], Order[does_not_exist2{f}#1,DESC,FIRST], Order[emp_no{f}#2,ASC,LAST]]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist1{f}#0, does_not_exist2{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected new file mode 100644 index 0000000000000..f57ed4d6c6fda --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[TOLONG(does_not_exist1{r}#0) + 1[INTEGER],ASC,LAST], Order[does_not_exist2{r}#1,DESC,FIRST], Order[emp_no{f}#2,ASC,LAST]]] + \_Eval[[null[NULL] AS does_not_exist1#0, null[NULL] AS does_not_exist2#1]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/query.esql new file mode 100644 index 0000000000000..df129647e7c8a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| SORT does_not_exist1::LONG + 1, does_not_exist2 DESC, emp_no ASC diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected new file mode 100644 index 0000000000000..1b58079c3c0e9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[does_not_exist_field{f}#0],[does_not_exist_field{f}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/analysis.expected new file mode 100644 index 0000000000000..dc5330d4bd4ae --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[does_not_exist_field{r}#0],[does_not_exist_field{r}#0]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/query.esql new file mode 100644 index 0000000000000..d13f24be60435 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS BY does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected new file mode 100644 index 0000000000000..456247586e3be --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[],[COUNT(does_not_exist_field{f}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/analysis.expected new file mode 100644 index 0000000000000..bce83c7e94ff2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[],[COUNT(does_not_exist_field{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt#1]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/query.esql new file mode 100644 index 0000000000000..2e1086f20474e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS cnt = COUNT(does_not_exist_field) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/analysis.expected new file mode 100644 index 0000000000000..0e4402c48cdba --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{f}#0) > 0[INTEGER]] AS c#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist1{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/analysis.expected new file mode 100644 index 0000000000000..31ed40e729ba7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{r}#0) > 0[INTEGER]] AS c#1]] + \_Eval[[null[NULL] AS does_not_exist1#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/query.esql new file mode 100644 index 0000000000000..c761b990a28aa --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected new file mode 100644 index 0000000000000..860ec580b8dd8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[does_not_exist2{f}#0, emp_no{f}#1],[SUM(TODOUBLE(does_not_exist1{f}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{f}#0, emp_no{f}#1]] + \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#1, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26, does_not_exist2{f}#0, does_not_exist1{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected new file mode 100644 index 0000000000000..3bd26f310af82 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[does_not_exist2{r}#0, emp_no{f}#1],[SUM(TODOUBLE(does_not_exist1{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{r}#0, emp_no{f}#1]] + \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist1#2]] + \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#1, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/query.esql new file mode 100644 index 0000000000000..ecc9a01cd10d1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected new file mode 100644 index 0000000000000..1ad181f29d080 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{f}#0) > 0[INTEGER] OR emp_no{f}#1 +9 > 0[INTEGER] OR TOLONG(does_not_exist2{f}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{f}#4)] AS c2#5]] + \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#8, first_name{f}#9, gender{f}#10, height{f}#11, height.float{f}#12, height.half_float{f}#13, height.scaled_float{f}#14, hire_date{f}#15, is_rehired{f}#16, job_positions{f}#17, languages{f}#18, languages.byte{f}#19, languages.long{f}#20, languages.short{f}#21, last_name{f}#22, salary{f}#23, salary_change{f}#24, salary_change.int{f}#25, salary_change.keyword{f}#26, salary_change.long{f}#27, still_hired{f}#28, does_not_exist1{f}#0, does_not_exist2{f}#2, does_not_exist3{f}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected new file mode 100644 index 0000000000000..54ebfb4203f39 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{r}#0) > 0[INTEGER] OR emp_no{f}#1 +1 > 0[INTEGER] OR TOLONG(does_not_exist2{r}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{r}#4)] AS c2#5]] + \_Eval[[null[NULL] AS does_not_exist1#0, null[NULL] AS does_not_exist2#2, null[NULL] AS does_not_exist3#4]] + \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#8, first_name{f}#9, gender{f}#10, height{f}#11, height.float{f}#12, height.half_float{f}#13, height.scaled_float{f}#14, hire_date{f}#15, is_rehired{f}#16, job_positions{f}#17, languages{f}#18, languages.byte{f}#19, languages.long{f}#20, languages.short{f}#21, last_name{f}#22, salary{f}#23, salary_change{f}#24, salary_change.int{f}#25, salary_change.keyword{f}#26, salary_change.long{f}#27, still_hired{f}#28] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/query.esql new file mode 100644 index 0000000000000..6f052b1a79cb2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS c1 = COUNT(*) WHERE does_not_exist1::LONG > 0 OR emp_no > 0 OR does_not_exist2::LONG < 100, + c2 = COUNT(*) WHERE does_not_exist3 IS NULL diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected new file mode 100644 index 0000000000000..27b179dff2e21 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[does_not_exist2{f}#0],[SUM(TODOUBLE(does_not_exist1{f}#1),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#2, does_not_exist2{f}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist2{f}#0, does_not_exist1{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/analysis.expected new file mode 100644 index 0000000000000..75f108928c116 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[does_not_exist2{r}#0],[SUM(TODOUBLE(does_not_exist1{r}#1),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#2, does_not_exist2{r}#0]] + \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist1#1]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/query.esql new file mode 100644 index 0000000000000..4b45cf86d8cb5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected new file mode 100644 index 0000000000000..021eab43d5186 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TODOUBLE(does_not_exist2{f}#0) + TODOUBLE(does_not_exist3{f}#1) AS s0#2, emp_no{f}#3 AS s1#4],[SUM(TODOUBLE(does_not_exist1{f}#5),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + s0{r}#2 + s1{r}#4 AS sum#6, s0{r}#2, s1{r}#4]] + \_EsRelation[employees][avg_worked_seconds{f}#7, birth_date{f}#8, emp_no{f}#3, first_name{f}#9, gender{f}#10, height{f}#11, height.float{f}#12, height.half_float{f}#13, height.scaled_float{f}#14, hire_date{f}#15, is_rehired{f}#16, job_positions{f}#17, languages{f}#18, languages.byte{f}#19, languages.long{f}#20, languages.short{f}#21, last_name{f}#22, salary{f}#23, salary_change{f}#24, salary_change.int{f}#25, salary_change.keyword{f}#26, salary_change.long{f}#27, still_hired{f}#28, does_not_exist2{f}#0, does_not_exist3{f}#1, does_not_exist1{f}#5, s0{f}#29] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected new file mode 100644 index 0000000000000..a877b9d0f0588 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TODOUBLE(does_not_exist2{r}#0) + TODOUBLE(does_not_exist3{r}#1) AS s0#2, emp_no{f}#3 AS s1#4],[SUM(TODOUBLE(does_not_exist1{r}#5),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + s0{r}#2 + s1{r}#4 AS sum#6, s0{r}#2, s1{r}#4]] + \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist3#1, null[NULL] AS does_not_exist1#5, null[NULL] AS s0#7]] + \_EsRelation[employees][avg_worked_seconds{f}#8, birth_date{f}#9, emp_no{f}#3, first_name{f}#10, gender{f}#11, height{f}#12, height.float{f}#13, height.half_float{f}#14, height.scaled_float{f}#15, hire_date{f}#16, is_rehired{f}#17, job_positions{f}#18, languages{f}#19, languages.byte{f}#20, languages.long{f}#21, languages.short{f}#22, last_name{f}#23, salary{f}#24, salary_change{f}#25, salary_change.int{f}#26, salary_change.keyword{f}#27, salary_change.long{f}#28, still_hired{f}#29] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/query.esql new file mode 100644 index 0000000000000..c8ed9b159cb2a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS sum = SUM(does_not_exist1::DOUBLE) + s0 + s1 BY s0 = does_not_exist2::DOUBLE + does_not_exist3::DOUBLE, s1 = emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected new file mode 100644 index 0000000000000..2ad8609f9bac6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TODOUBLE(does_not_exist2{f}#0) AS d2#1, emp_no{f}#2],[SUM(TODOUBLE(does_not_exist1{f}#3),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + d2{r}#1 AS s#4, d2{r}#1, emp_no{f}#2]] + \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#2, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26, does_not_exist2{f}#0, does_not_exist1{f}#3, d2{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected new file mode 100644 index 0000000000000..f06e76b90283d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TODOUBLE(does_not_exist2{r}#0) AS d2#1, emp_no{f}#2],[SUM(TODOUBLE(does_not_exist1{r}#3),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + d2{r}#1 AS s#4, d2{r}#1, emp_no{f}#2]] + \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist1#3, null[NULL] AS d2#5]] + \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#2, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/query.esql new file mode 100644 index 0000000000000..d548e72eda5de --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS s = SUM(does_not_exist1::DOUBLE) + d2 BY d2 = does_not_exist2::DOUBLE, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/load/analysis.expected new file mode 100644 index 0000000000000..d413739fd03bc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist{f}#0) > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/analysis.expected new file mode 100644 index 0000000000000..d56f0e5969628 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist{r}#0) > 0[INTEGER]] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/query.esql new file mode 100644 index 0000000000000..e713ad65f4f21 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| WHERE does_not_exist::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/load/analysis.expected new file mode 100644 index 0000000000000..8d9fcfe30c2c2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist1{f}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER] AND TOLONG(does_not_exist2{f}#2) < 100[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#1, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist1{f}#0, does_not_exist2{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/analysis.expected new file mode 100644 index 0000000000000..6364f29c1da43 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist1{r}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER] AND TOLONG(does_not_exist2{r}#2) < 100[INTEGER]] + \_Eval[[null[NULL] AS does_not_exist1#0, null[NULL] AS does_not_exist2#2]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#1, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/query.esql new file mode 100644 index 0000000000000..ca0a222d0d3c8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| WHERE does_not_exist1::LONG > 0 OR emp_no > 0 AND does_not_exist2::LONG < 100 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/load/analysis.expected new file mode 100644 index 0000000000000..4e5bd4c4b8b68 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist{f}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#1, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/analysis.expected new file mode 100644 index 0000000000000..f6c3ff4db63bb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist{r}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER]] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#1, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/query.esql new file mode 100644 index 0000000000000..733eddf433f08 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| WHERE does_not_exist::LONG > 0 OR emp_no > 0 From 6aeccac178d014812bb4ba860300a16cf0387f4f Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 3 Feb 2026 17:59:00 +0200 Subject: [PATCH 015/137] TEMP --- .../elasticsearch/xpack/esql/optimizer/GoldenTestCase.java | 4 +--- .../testStatsMultipleCountWhere/load/analysis.expected | 2 +- .../testStatsMultipleCountWhere/nullify/analysis.expected | 2 +- .../testStatsMultipleCountWhere/query.esql | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 5a3390f4d530c..95e2c140c197d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -25,14 +25,12 @@ import org.elasticsearch.xpack.esql.analysis.Analyzer; import org.elasticsearch.xpack.esql.analysis.AnalyzerContext; import org.elasticsearch.xpack.esql.analysis.EnrichResolution; -import org.elasticsearch.xpack.esql.analysis.UnmappedResolution; import org.elasticsearch.xpack.esql.core.expression.FoldContext; import org.elasticsearch.xpack.esql.core.tree.Node; import org.elasticsearch.xpack.esql.expression.function.EsqlFunctionRegistry; import org.elasticsearch.xpack.esql.inference.InferenceResolution; import org.elasticsearch.xpack.esql.parser.EsqlParser; import org.elasticsearch.xpack.esql.plan.QueryPlan; -import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.esql.plan.physical.ExchangeExec; import org.elasticsearch.xpack.esql.plan.physical.ExchangeSinkExec; import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; @@ -68,8 +66,8 @@ import static org.elasticsearch.xpack.esql.EsqlTestUtils.TEST_VERIFIER; import static org.elasticsearch.xpack.esql.EsqlTestUtils.randomMinimumVersion; import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning; -import static org.elasticsearch.xpack.esql.plan.QuerySettings.UNMAPPED_FIELDS; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.defaultLookupResolution; +import static org.elasticsearch.xpack.esql.plan.QuerySettings.UNMAPPED_FIELDS; /** See GoldenTestsReadme.md for more information about these tests. */ @Listeners({ GoldenTestCase.GoldenTestReproduceInfoPrinter.class }) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected index 1ad181f29d080..ae6b7c030b624 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] \_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{f}#0) > 0[INTEGER] OR emp_no{f}#1 -9 > 0[INTEGER] OR TOLONG(does_not_exist2{f}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{f}#4)] AS c2#5]] +523 > 0[INTEGER] OR TOLONG(does_not_exist2{f}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{f}#4)] AS c2#5]] \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#8, first_name{f}#9, gender{f}#10, height{f}#11, height.float{f}#12, height.half_float{f}#13, height.scaled_float{f}#14, hire_date{f}#15, is_rehired{f}#16, job_positions{f}#17, languages{f}#18, languages.byte{f}#19, languages.long{f}#20, languages.short{f}#21, last_name{f}#22, salary{f}#23, salary_change{f}#24, salary_change.int{f}#25, salary_change.keyword{f}#26, salary_change.long{f}#27, still_hired{f}#28, does_not_exist1{f}#0, does_not_exist2{f}#2, does_not_exist3{f}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected index 54ebfb4203f39..ed20d1ae39bbe 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected @@ -1,5 +1,5 @@ Limit[1000[INTEGER],false,false] \_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{r}#0) > 0[INTEGER] OR emp_no{f}#1 -1 > 0[INTEGER] OR TOLONG(does_not_exist2{r}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{r}#4)] AS c2#5]] +485 > 0[INTEGER] OR TOLONG(does_not_exist2{r}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{r}#4)] AS c2#5]] \_Eval[[null[NULL] AS does_not_exist1#0, null[NULL] AS does_not_exist2#2, null[NULL] AS does_not_exist3#4]] \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#8, first_name{f}#9, gender{f}#10, height{f}#11, height.float{f}#12, height.half_float{f}#13, height.scaled_float{f}#14, hire_date{f}#15, is_rehired{f}#16, job_positions{f}#17, languages{f}#18, languages.byte{f}#19, languages.long{f}#20, languages.short{f}#21, last_name{f}#22, salary{f}#23, salary_change{f}#24, salary_change.int{f}#25, salary_change.keyword{f}#26, salary_change.long{f}#27, still_hired{f}#28] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/query.esql index 6f052b1a79cb2..3078319477f7f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/query.esql @@ -1,3 +1,3 @@ -SET unmapped_fields="nullify"; FROM employees +SET unmapped_fields="load"; FROM employees | STATS c1 = COUNT(*) WHERE does_not_exist1::LONG > 0 OR emp_no > 0 OR does_not_exist2::LONG < 100, c2 = COUNT(*) WHERE does_not_exist3 IS NULL From d47e18b35627013f2d3b30356253b37c5b8676d7 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 3 Feb 2026 18:26:42 +0200 Subject: [PATCH 016/137] Fix query.esql --- .../xpack/esql/optimizer/GoldenTestCase.java | 30 ++++++++++++------- .../testDrop/{ => load}/query.esql | 0 .../testDrop/nullify/query.esql | 2 ++ .../{ => load}/query.esql | 0 .../nullify/query.esql | 2 ++ .../testEval/{ => load}/query.esql | 0 .../testEval/nullify/query.esql | 2 ++ .../{ => load}/query.esql | 0 .../testEvalAfterKeepStar/nullify/query.esql | 4 +++ .../{ => load}/query.esql | 0 .../nullify/query.esql | 4 +++ .../testEvalAndKeep/{ => load}/query.esql | 0 .../testEvalAndKeep/nullify/query.esql | 3 ++ .../testEvalCast/{ => load}/query.esql | 0 .../testEvalCast/nullify/query.esql | 2 ++ .../testEvalCastInPlace/{ => load}/query.esql | 0 .../testEvalCastInPlace/nullify/query.esql | 2 ++ .../testEvalReplace/{ => load}/query.esql | 0 .../testEvalReplace/nullify/query.esql | 3 ++ .../testInlineStats/{ => load}/query.esql | 0 .../testInlineStats/nullify/query.esql | 2 ++ .../testKeep/{ => load}/query.esql | 0 .../testKeep/nullify/query.esql | 2 ++ .../{ => load}/query.esql | 0 .../nullify/query.esql | 2 ++ .../testKeepRepeated/{ => load}/query.esql | 0 .../testKeepRepeated/nullify/query.esql | 2 ++ .../testKeepThenEval/{ => load}/query.esql | 0 .../testKeepThenEval/nullify/query.esql | 3 ++ .../testMultipleEval/{ => load}/query.esql | 0 .../testMultipleEval/nullify/query.esql | 4 +++ .../testMvExpand/{ => load}/query.esql | 0 .../testMvExpand/nullify/query.esql | 2 ++ .../testRename/{ => load}/query.esql | 0 .../testRename/nullify/query.esql | 2 ++ .../testRenameEval/{ => load}/query.esql | 0 .../testRenameEval/nullify/query.esql | 3 ++ .../testRenameRepeated/{ => load}/query.esql | 0 .../testRenameRepeated/nullify/query.esql | 2 ++ .../testSort/{ => load}/query.esql | 0 .../testSort/nullify/query.esql | 2 ++ .../testSortExpression/{ => load}/query.esql | 0 .../testSortExpression/nullify/query.esql | 2 ++ .../testSortMultiple/{ => load}/query.esql | 0 .../testSortMultiple/nullify/query.esql | 2 ++ .../testStatsBy/{ => load}/query.esql | 0 .../testStatsBy/nullify/query.esql | 2 ++ .../testStatsCount/{ => load}/query.esql | 0 .../testStatsCount/nullify/query.esql | 2 ++ .../testStatsCountWhere/{ => load}/query.esql | 0 .../testStatsCountWhere/nullify/query.esql | 2 ++ .../testStatsMultiple/{ => load}/query.esql | 0 .../testStatsMultiple/nullify/query.esql | 2 ++ .../load/analysis.expected | 2 +- .../{ => load}/query.esql | 0 .../nullify/analysis.expected | 2 +- .../nullify/query.esql | 3 ++ .../testStatsSumBy/{ => load}/query.esql | 0 .../testStatsSumBy/nullify/query.esql | 2 ++ .../{ => load}/query.esql | 0 .../testStatsSumByComplex/nullify/query.esql | 2 ++ .../{ => load}/query.esql | 0 .../testStatsSumByMultiple/nullify/query.esql | 2 ++ .../testWhere/{ => load}/query.esql | 0 .../testWhere/nullify/query.esql | 2 ++ .../testWhereComplex/{ => load}/query.esql | 0 .../testWhereComplex/nullify/query.esql | 2 ++ .../testWhereOr/{ => load}/query.esql | 0 .../testWhereOr/nullify/query.esql | 2 ++ .../bucket/query.esql | 4 +++ .../date_trunc/query.esql | 4 +++ .../round_to/query.esql | 4 +++ .../bucket/query.esql | 4 +++ .../date_trunc/query.esql | 4 +++ .../round_to/query.esql | 4 +++ .../bucket/query.esql | 2 ++ .../date_trunc/query.esql | 2 ++ .../round_to/query.esql | 2 ++ .../bucket/query.esql | 2 ++ .../date_trunc/query.esql | 2 ++ .../round_to/query.esql | 2 ++ .../bucket/query.esql | 2 ++ .../date_trunc/query.esql | 2 ++ .../round_to/query.esql | 2 ++ .../bucket/date_range/query.esql | 3 ++ .../bucket/keyword_equality/query.esql | 3 ++ .../bucket/keyword_match/query.esql | 3 ++ .../date_trunc/date_range/query.esql | 3 ++ .../date_trunc/keyword_equality/query.esql | 3 ++ .../date_trunc/keyword_match/query.esql | 3 ++ .../round_to/date_range/query.esql | 3 ++ .../round_to/keyword_equality/query.esql | 3 ++ .../round_to/keyword_match/query.esql | 3 ++ .../bucket/query.esql | 2 ++ .../date_trunc/query.esql | 2 ++ .../round_to/query.esql | 2 ++ .../date_trunc/query.esql | 5 ++++ .../round_to/query.esql | 5 ++++ .../byte/query.esql | 2 ++ .../date/query.esql | 2 ++ .../date_nanos/query.esql | 2 ++ .../double/query.esql | 2 ++ .../float/query.esql | 2 ++ .../half_float/query.esql | 2 ++ .../integer/query.esql | 2 ++ .../long/query.esql | 2 ++ .../scaled_float/query.esql | 2 ++ .../short/query.esql | 2 ++ ...l_reduce_physical_optimization_data_driver | 4 +++ .../local_reduce_planned_data_driver | 5 ++++ .../local_reduce_planned_reduce_driver | 5 ++++ ...l_reduce_physical_optimization_data_driver | 6 ++++ .../local_reduce_planned_data_driver | 6 ++++ .../local_reduce_planned_reduce_driver | 5 ++++ ...l_reduce_physical_optimization_data_driver | 6 ++++ .../local_reduce_planned_data_driver | 6 ++++ .../local_reduce_planned_reduce_driver | 5 ++++ ...l_reduce_physical_optimization_data_driver | 25 ++++++++++++++++ .../local_reduce_planned_data_driver | 9 ++++++ .../local_reduce_planned_reduce_driver | 5 ++++ ...l_reduce_physical_optimization_data_driver | 4 +++ .../local_reduce_planned_data_driver | 5 ++++ .../local_reduce_planned_reduce_driver | 5 ++++ ...l_reduce_physical_optimization_data_driver | 4 +++ .../local_reduce_planned_data_driver | 5 ++++ .../local_reduce_planned_reduce_driver | 5 ++++ ...l_reduce_physical_optimization_data_driver | 7 +++++ ...reduce_physical_optimization_reduce_driver | 3 ++ .../local_reduce_planned_data_driver | 7 +++++ .../local_reduce_planned_reduce_driver | 3 ++ ...l_reduce_physical_optimization_data_driver | 4 +++ .../local_reduce_planned_data_driver | 5 ++++ .../local_reduce_planned_reduce_driver | 5 ++++ ...l_reduce_physical_optimization_data_driver | 17 +++++++++++ .../local_reduce_planned_data_driver | 6 ++++ .../local_reduce_planned_reduce_driver | 5 ++++ ...l_reduce_physical_optimization_data_driver | 4 +++ .../local_reduce_planned_data_driver | 5 ++++ .../local_reduce_planned_reduce_driver | 5 ++++ ...l_reduce_physical_optimization_data_driver | 4 +++ .../local_reduce_planned_data_driver | 5 ++++ .../local_reduce_planned_reduce_driver | 5 ++++ 142 files changed, 409 insertions(+), 12 deletions(-) rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/round_to/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/round_to/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/long/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 95e2c140c197d..9044b2e9918dd 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -201,8 +201,8 @@ private void doTest() { private List> doTests() throws IOException { var statement = EsqlParser.INSTANCE.createStatement(esqlQuery); var parsedPlan = statement.plan(); - Files.createDirectories(PathUtils.get(basePath.toString(), testName)); - Files.writeString(PathUtils.get(basePath.toString(), testName, "query.esql"), esqlQuery); + Files.createDirectories(PathUtils.get(basePath.toString(), pathArray(0))); + Files.writeString(outputPath("query.esql"), esqlQuery); var analyzer = new Analyzer( new AnalyzerContext( EsqlTestUtils.TEST_CFG, @@ -303,6 +303,14 @@ private List> doTests() throws IOException { return result; } + // FIXME(gal, NOCOMMIT) Not a fan of this signature + private String[] pathArray(int extraElements) { + var paths = new String[nestedPath.length + 1 + extraElements]; + paths[0] = testName; + System.arraycopy(nestedPath, 0, paths, 1, nestedPath.length); + return paths; + } + private enum TestResult { SUCCESS, FAILURE, @@ -335,7 +343,7 @@ private List> addDualPlanResult( } private > TestResult verifyOrWrite(T plan, Stage stage) throws IOException { - return verifyOrWrite(plan, outputPath(stage)); + return verifyOrWrite(plan, stageOutputPath(stage)); } private > TestResult verifyOrWrite(T plan, Path outputFile) throws IOException { @@ -352,15 +360,17 @@ private > TestResult verifyOrWrite(T plan, Path outputFil } } - private Path outputPath(Stage stage) { - return outputPath(((SingleFileOutput) stage.fileOutput).output()); + private Path stageOutputPath(Stage stage) { + return stageOutputPath(((SingleFileOutput) stage.fileOutput).output()); } - private Path outputPath(String stageName) { - var paths = new String[nestedPath.length + 2]; - paths[0] = testName; - System.arraycopy(nestedPath, 0, paths, 1, nestedPath.length); - paths[paths.length - 1] = Strings.format("%s.expected", stageName); + private Path stageOutputPath(String stageName) { + return outputPath(stageName + ".expected"); + } + + private Path outputPath(String fileName) { + var paths = pathArray(1); + paths[paths.length - 1] = fileName; return PathUtils.get(basePath.toString(), paths); } diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/query.esql new file mode 100644 index 0000000000000..deb3bd1826afc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| DROP does_not_exist_field, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/query.esql new file mode 100644 index 0000000000000..7064d202cbedc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| DROP emp_*, does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/query.esql new file mode 100644 index 0000000000000..8a1085423e2ed --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL x = does_not_exist_field::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/query.esql new file mode 100644 index 0000000000000..6f6ce85c55b54 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees +| KEEP * +| EVAL x = emp_no + 1 +| EVAL y = does_not_exist_field::DOUBLE + 2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/query.esql new file mode 100644 index 0000000000000..b96afd6be3bc8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees +| KEEP emp_no, * +| EVAL x = emp_no + 1 +| EVAL y = emp_does_not_exist_field::DOUBLE + 2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/query.esql new file mode 100644 index 0000000000000..b835bd71bd018 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL x = does_not_exist_field1::INTEGER + 42 +| KEEP does_not_exist_field1, does_not_exist_field2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/query.esql new file mode 100644 index 0000000000000..645643aa1255c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL x = does_not_exist_field::LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/query.esql new file mode 100644 index 0000000000000..91f24cce1fb92 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL does_not_exist_field::LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql new file mode 100644 index 0000000000000..241e39491fa9a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL x = does_not_exist_field::DOUBLE + 1 +| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql new file mode 100644 index 0000000000000..314e176a1843d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| INLINE STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/query.esql new file mode 100644 index 0000000000000..aa0cb37ad9b24 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| KEEP does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/query.esql new file mode 100644 index 0000000000000..0a9ada347fc6a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| KEEP emp_*, does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/query.esql new file mode 100644 index 0000000000000..cef77352827e4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| KEEP does_not_exist_field, does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql new file mode 100644 index 0000000000000..4337b35ba4b2e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| KEEP does_not_exist_field +| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/query.esql new file mode 100644 index 0000000000000..1c122d2bc9737 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL a = 1 +| EVAL x = a + b::DOUBLE +| EVAL y = b::DOUBLE + c::DOUBLE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/query.esql new file mode 100644 index 0000000000000..4028dd22bad3d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| MV_EXPAND does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/query.esql new file mode 100644 index 0000000000000..5b99834da2a5a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| RENAME does_not_exist_field AS now_it_does, emp_no AS employee_number diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql new file mode 100644 index 0000000000000..7475a95153a3a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| RENAME emp_no AS employee_number +| EVAL x = does_not_exist::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/query.esql new file mode 100644 index 0000000000000..db1febeb315ad --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| RENAME does_not_exist_field AS now_it_does, neither_does_this AS now_it_does, emp_no AS employee_number diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/query.esql new file mode 100644 index 0000000000000..e2e03a32e90b3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| SORT does_not_exist ASC diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/query.esql new file mode 100644 index 0000000000000..4f3e51522c415 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| SORT does_not_exist::LONG + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/query.esql new file mode 100644 index 0000000000000..7b1dadb3f7ed2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| SORT does_not_exist1::LONG + 1, does_not_exist2 DESC, emp_no ASC diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/query.esql new file mode 100644 index 0000000000000..b4ef8dbc01160 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS BY does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/query.esql new file mode 100644 index 0000000000000..e8fb3888650cf --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS cnt = COUNT(does_not_exist_field) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/query.esql new file mode 100644 index 0000000000000..7c028cc985242 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/query.esql new file mode 100644 index 0000000000000..6887849dbdcd4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected index ae6b7c030b624..7a9858e13cc71 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] \_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{f}#0) > 0[INTEGER] OR emp_no{f}#1 -523 > 0[INTEGER] OR TOLONG(does_not_exist2{f}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{f}#4)] AS c2#5]] +5 > 0[INTEGER] OR TOLONG(does_not_exist2{f}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{f}#4)] AS c2#5]] \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#8, first_name{f}#9, gender{f}#10, height{f}#11, height.float{f}#12, height.half_float{f}#13, height.scaled_float{f}#14, hire_date{f}#15, is_rehired{f}#16, job_positions{f}#17, languages{f}#18, languages.byte{f}#19, languages.long{f}#20, languages.short{f}#21, last_name{f}#22, salary{f}#23, salary_change{f}#24, salary_change.int{f}#25, salary_change.keyword{f}#26, salary_change.long{f}#27, still_hired{f}#28, does_not_exist1{f}#0, does_not_exist2{f}#2, does_not_exist3{f}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected index ed20d1ae39bbe..1b1b5a8f9580e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected @@ -1,5 +1,5 @@ Limit[1000[INTEGER],false,false] \_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{r}#0) > 0[INTEGER] OR emp_no{f}#1 -485 > 0[INTEGER] OR TOLONG(does_not_exist2{r}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{r}#4)] AS c2#5]] +7 > 0[INTEGER] OR TOLONG(does_not_exist2{r}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{r}#4)] AS c2#5]] \_Eval[[null[NULL] AS does_not_exist1#0, null[NULL] AS does_not_exist2#2, null[NULL] AS does_not_exist3#4]] \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#8, first_name{f}#9, gender{f}#10, height{f}#11, height.float{f}#12, height.half_float{f}#13, height.scaled_float{f}#14, hire_date{f}#15, is_rehired{f}#16, job_positions{f}#17, languages{f}#18, languages.byte{f}#19, languages.long{f}#20, languages.short{f}#21, last_name{f}#22, salary{f}#23, salary_change{f}#24, salary_change.int{f}#25, salary_change.keyword{f}#26, salary_change.long{f}#27, still_hired{f}#28] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/query.esql new file mode 100644 index 0000000000000..6f052b1a79cb2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS c1 = COUNT(*) WHERE does_not_exist1::LONG > 0 OR emp_no > 0 OR does_not_exist2::LONG < 100, + c2 = COUNT(*) WHERE does_not_exist3 IS NULL diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/query.esql new file mode 100644 index 0000000000000..29d53f6beba5b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/query.esql new file mode 100644 index 0000000000000..d4152fb7a5e2f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS sum = SUM(does_not_exist1::DOUBLE) + s0 + s1 BY s0 = does_not_exist2::DOUBLE + does_not_exist3::DOUBLE, s1 = emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/query.esql new file mode 100644 index 0000000000000..c9f8f55bbee50 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS s = SUM(does_not_exist1::DOUBLE) + d2 BY d2 = does_not_exist2::DOUBLE, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/query.esql new file mode 100644 index 0000000000000..3d9a2e14cc93c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| WHERE does_not_exist::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/query.esql new file mode 100644 index 0000000000000..6da7b544c73b8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| WHERE does_not_exist1::LONG > 0 OR emp_no > 0 AND does_not_exist2::LONG < 100 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/query.esql new file mode 100644 index 0000000000000..6a4dcd6d7226f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| WHERE does_not_exist::LONG > 0 OR emp_no > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/query.esql new file mode 100644 index 0000000000000..b615c9c44e290 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/query.esql @@ -0,0 +1,4 @@ +from all_types +| fork (where integer > 100) +(where keyword : "keyword") +| stats count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/query.esql new file mode 100644 index 0000000000000..58c5f6728342c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/query.esql @@ -0,0 +1,4 @@ +from all_types +| fork (where integer > 100) +(where keyword : "keyword") +| stats count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/query.esql new file mode 100644 index 0000000000000..c8f08b2e6dd38 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/query.esql @@ -0,0 +1,4 @@ +from all_types +| fork (where integer > 100) +(where keyword : "keyword") +| stats count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/query.esql new file mode 100644 index 0000000000000..f24a6518c3f51 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/query.esql @@ -0,0 +1,4 @@ +from all_types +| rename integer as language_code +| lookup join languages_lookup on language_code +| stats count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/query.esql new file mode 100644 index 0000000000000..74629dcb51051 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/query.esql @@ -0,0 +1,4 @@ +from all_types +| rename integer as language_code +| lookup join languages_lookup on language_code +| stats count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/query.esql new file mode 100644 index 0000000000000..7472b3a4d943e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/query.esql @@ -0,0 +1,4 @@ +from all_types +| rename integer as language_code +| lookup join languages_lookup on language_code +| stats count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/query.esql new file mode 100644 index 0000000000000..22fca42d878fd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/query.esql new file mode 100644 index 0000000000000..fa1300117c2a8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/round_to/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/round_to/query.esql new file mode 100644 index 0000000000000..46e5cd746c53f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/round_to/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/query.esql new file mode 100644 index 0000000000000..22fca42d878fd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/query.esql new file mode 100644 index 0000000000000..fa1300117c2a8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/round_to/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/round_to/query.esql new file mode 100644 index 0000000000000..46e5cd746c53f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/round_to/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/query.esql new file mode 100644 index 0000000000000..54b417415ee19 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats sum(long), count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/query.esql new file mode 100644 index 0000000000000..c9af83d6cbaac --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats sum(long), count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/query.esql new file mode 100644 index 0000000000000..48b94551ef462 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats sum(long), count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/query.esql new file mode 100644 index 0000000000000..d57165bff1599 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/query.esql @@ -0,0 +1,3 @@ +from all_types +| where date >= "2023-10-19" and date <= "2023-10-24" +| stats count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/query.esql new file mode 100644 index 0000000000000..b6ffb3562cf48 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/query.esql @@ -0,0 +1,3 @@ +from all_types +| where keyword == "keyword" +| stats count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/query.esql new file mode 100644 index 0000000000000..1b177e943af0f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/query.esql @@ -0,0 +1,3 @@ +from all_types +| where keyword : "keyword" +| stats count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/query.esql new file mode 100644 index 0000000000000..c6afebcab13d7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/query.esql @@ -0,0 +1,3 @@ +from all_types +| where date >= "2023-10-19" and date <= "2023-10-24" +| stats count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/query.esql new file mode 100644 index 0000000000000..031813404bc12 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/query.esql @@ -0,0 +1,3 @@ +from all_types +| where keyword == "keyword" +| stats count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/query.esql new file mode 100644 index 0000000000000..3c3cbc238870b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/query.esql @@ -0,0 +1,3 @@ +from all_types +| where keyword : "keyword" +| stats count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/query.esql new file mode 100644 index 0000000000000..c56287a3dee3f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/query.esql @@ -0,0 +1,3 @@ +from all_types +| where date >= "2023-10-19" and date <= "2023-10-24" +| stats count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/query.esql new file mode 100644 index 0000000000000..0e2c6e873cf48 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/query.esql @@ -0,0 +1,3 @@ +from all_types +| where keyword == "keyword" +| stats count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/query.esql new file mode 100644 index 0000000000000..d252b63236f6b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/query.esql @@ -0,0 +1,3 @@ +from all_types +| where keyword : "keyword" +| stats count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/query.esql new file mode 100644 index 0000000000000..6309500488457 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) where long > 10 by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/query.esql new file mode 100644 index 0000000000000..039fd5ff287a6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) where long > 10 by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/query.esql new file mode 100644 index 0000000000000..33092020e833b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) where long > 10 by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/query.esql new file mode 100644 index 0000000000000..6756737f704e2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/query.esql @@ -0,0 +1,5 @@ +from all_types +| sort date +| eval x = date_trunc(1 day, date) +| keep alias_integer, date, x +| limit 5 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/query.esql new file mode 100644 index 0000000000000..327c15df1eb1c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/query.esql @@ -0,0 +1,5 @@ +from all_types +| sort date +| eval x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") +| keep alias_integer, date, x +| limit 5 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/query.esql new file mode 100644 index 0000000000000..883ffe342e7d4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(byte, 2,1,3,4) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/query.esql new file mode 100644 index 0000000000000..2f79776c6dda5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(date, "2023-10-20"::date,"2023-10-21"::date,"2023-10-22"::date,"2023-10-23"::date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/query.esql new file mode 100644 index 0000000000000..ed625ca873010 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(date_nanos, "2023-10-20"::date_nanos,"2023-10-21"::date_nanos,"2023-10-22"::date_nanos,"2023-10-23"::date_nanos) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/query.esql new file mode 100644 index 0000000000000..c4de6bf1e06a3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(double, 1.0,2.0,3.0,4.0) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/query.esql new file mode 100644 index 0000000000000..1d66674da19c1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(float, 3.0,2.0,1.0,4.0) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/query.esql new file mode 100644 index 0000000000000..eb1740cb34fd4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(half_float, 4.0,2.0,3.0,1.0) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/query.esql new file mode 100644 index 0000000000000..347e5c1c1f33e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(integer, 1,2,3,4) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/long/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/long/query.esql new file mode 100644 index 0000000000000..2af1315b103ac --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/long/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(long, 1697760000000,1697846400000,1697932800000,1698019200000) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/query.esql new file mode 100644 index 0000000000000..bc01ac6cabd48 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(scaled_float, 4.0,3.0,2.0,1.0) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/query.esql new file mode 100644 index 0000000000000..f9618eba09919 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(short, 1,3,2,4) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver new file mode 100644 index 0000000000000..71c01677f83a5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver @@ -0,0 +1,4 @@ +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[_doc{f}#3, hire_date{f}#1]] + \_FieldExtractExec[hire_date{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver new file mode 100644 index 0000000000000..fc4d011c9a8fb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}#3, hire_date{f}#1]] +\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver new file mode 100644 index 0000000000000..4b4fc0c891ac1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> + \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver new file mode 100644 index 0000000000000..8f49d89b830ce --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver @@ -0,0 +1,6 @@ +ExchangeSinkExec[[hire_date{f}#0, $$order_by$0{r}#1],false] +\_ProjectExec[[_doc{f}#2, $$order_by$0{r}#1]] + \_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],36] + \_EvalExec[[SIN(height{f}#3) * 2[INTEGER] AS $$order_by$0#1]] + \_FieldExtractExec[height{f}#3]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#2], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver new file mode 100644 index 0000000000000..9ce3f748778c1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver @@ -0,0 +1,6 @@ +ExchangeSinkExec[[hire_date{f}#0, $$order_by$0{r}#1],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}#2, $$order_by$0{r}#1]] +\_TopN[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}#3) * 2[INTEGER] AS $$order_by$0#1]] + \_EsRelation[employees][_doc{f}#2, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#3, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#0, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver new file mode 100644 index 0000000000000..d2459818c5588 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[hire_date{f}#0, $$order_by$0{r}#1],false] +\_ProjectExec[[hire_date{f}#0, $$order_by$0{r}#1]] + \_FieldExtractExec[hire_date{f}#0]<[],[]> + \_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#2, $$order_by$0{r}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver new file mode 100644 index 0000000000000..460cbcab3451e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver @@ -0,0 +1,6 @@ +ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2],false] +\_ProjectExec[[_doc{f}#3, height{f}#0, $$order_by$0{r}#2]] + \_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],36] + \_EvalExec[[SIN(height{f}#0) * 2[INTEGER] AS $$order_by$0#2]] + \_FieldExtractExec[height{f}#0]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver new file mode 100644 index 0000000000000..932c4834e7e80 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver @@ -0,0 +1,6 @@ +ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}#3, height{f}#0, $$order_by$0{r}#2]] +\_TopN[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}#0) * 2[INTEGER] AS $$order_by$0#2]] + \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#0, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver new file mode 100644 index 0000000000000..88c85960c5dd2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2],false] +\_ProjectExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2]] + \_FieldExtractExec[hire_date{f}#1]<[],[]> + \_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],44] + \_ExchangeSourceExec[[_doc{f}#3, height{f}#0, $$order_by$0{r}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver new file mode 100644 index 0000000000000..ebbbae1cfcc6d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver @@ -0,0 +1,25 @@ +ExchangeSinkExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] +\_ProjectExec[[_doc{f}#25, emp_no{f}#2, languages{f}#12, language_code{r}#23, language_name{f}#24]] + \_TopNExec[[Order[emp_no{f}#2,ASC,LAST]],20[INTEGER],82] + \_FieldExtractExec[emp_no{f}#2]<[],[]> + \_LookupJoinExec[[language_code{r}#23],[language_code{f}#26],[language_name{f}#24],null] + |_EvalExec[[languages{f}#12 AS language_code#23]] + | \_FieldExtractExec[languages{f}#12]<[],[]> + | \_EsQueryExec[employees], indexMode[standard], [_doc{f}#25], limit[], sort[] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query={ + "esql_single_value" : { + "field" : "emp_no", + "next" : { + "range" : { + "emp_no" : { + "gte" : 10091, + "lt" : 10094, + "time_zone" : "Z", + "boost" : 0.0 + } + } + }, + "source" : "emp_no >= 10091@4:9" + } +}, tags=[]]]] + \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +EsRelation[languages_lookup][LOOKUP][language_code{f}#26, language_name{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver new file mode 100644 index 0000000000000..7ff68ac134d83 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver @@ -0,0 +1,9 @@ +ExchangeSinkExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}#25, emp_no{f}#2, languages{f}#12, language_code{r}#23, language_name{f}#24]] +\_TopN[[Order[emp_no{f}#2,ASC,LAST]],20[INTEGER],false] + \_Join[LEFT,[language_code{r}#23],[language_code{f}#26],null] + |_Eval[[languages{f}#12 AS language_code#23]] + | \_Filter[emp_no{f}#2 >= 10091[INTEGER] AND emp_no{f}#2 < 10094[INTEGER]] + | \_EsRelation[employees][_doc{f}#25, avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#26, language_name{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver new file mode 100644 index 0000000000000..19c98b1780f37 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] +\_ProjectExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24]] + \_FieldExtractExec[avg_worked_seconds{f}#0, birth_date{f}#1, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<[],[]> + \_TopNExec[[Order[emp_no{f}#2,ASC,LAST]],20[INTEGER],430] + \_ExchangeSourceExec[[_doc{f}#25, emp_no{f}#2, languages{f}#12, language_code{r}#23, language_name{f}#24],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver new file mode 100644 index 0000000000000..e5de0b72a7705 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver @@ -0,0 +1,4 @@ +ExchangeSinkExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2],false] +\_ProjectExec[[_doc{f}#3, hire_date{f}#2, height{f}#1]] + \_FieldExtractExec[hire_date{f}#2, height{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#2, direction=ASC, nulls=LAST], FieldSort[field=height{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[32] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver new file mode 100644 index 0000000000000..4866ac15c30c3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}#3, hire_date{f}#2, height{f}#1]] +\_TopN[[Order[hire_date{f}#2,ASC,LAST], Order[height{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#1, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#2, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver new file mode 100644 index 0000000000000..ab96def3b448c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2],false] +\_ProjectExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2]] + \_FieldExtractExec[emp_no{f}#0]<[],[]> + \_TopNExec[[Order[hire_date{f}#2,ASC,LAST], Order[height{f}#1,ASC,LAST]],20[INTEGER],40] + \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#2, height{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver new file mode 100644 index 0000000000000..71c01677f83a5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver @@ -0,0 +1,4 @@ +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[_doc{f}#3, hire_date{f}#1]] + \_FieldExtractExec[hire_date{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver new file mode 100644 index 0000000000000..fc4d011c9a8fb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}#3, hire_date{f}#1]] +\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver new file mode 100644 index 0000000000000..4b4fc0c891ac1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> + \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver new file mode 100644 index 0000000000000..f0d827b7d0c99 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver @@ -0,0 +1,7 @@ +ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2]] + \_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] + \_MvExpandExec[job_positions{f}#3,job_positions{r}#1] + \_ProjectExec[[emp_no{f}#0, job_positions{f}#3, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0, job_positions{f}#3, salary{f}#2]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#4], limit[], sort[] estimatedRowSize[62] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver new file mode 100644 index 0000000000000..a9639e399dec8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver @@ -0,0 +1,3 @@ +ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] +\_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] + \_ExchangeSourceExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver new file mode 100644 index 0000000000000..baf5e66932990 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver @@ -0,0 +1,7 @@ +ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[emp_no{f}#0, job_positions{r}#1, salary{f}#2]] +\_TopN[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],false] + \_MvExpand[job_positions{f}#3,job_positions{r}#1] + \_Project[[emp_no{f}#0, job_positions{f}#3, salary{f}#2]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#3, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver new file mode 100644 index 0000000000000..a9639e399dec8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver @@ -0,0 +1,3 @@ +ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] +\_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] + \_ExchangeSourceExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver new file mode 100644 index 0000000000000..cebf3f704c28d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver @@ -0,0 +1,4 @@ +ExchangeSinkExec[[emp_no{f}#0, height{f}#1],false] +\_ProjectExec[[_doc{f}#2, height{f}#1]] + \_FieldExtractExec[height{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#2], limit[20], sort[[FieldSort[field=height{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver new file mode 100644 index 0000000000000..b2913dbdf505b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}#0, height{f}#1],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}#2, height{f}#1]] +\_TopN[[Order[height{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#2, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#0, first_name{f}#5, gender{f}#6, height{f}#1, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver new file mode 100644 index 0000000000000..3425364e715c1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}#0, height{f}#1],false] +\_ProjectExec[[emp_no{f}#0, height{f}#1]] + \_FieldExtractExec[emp_no{f}#0]<[],[]> + \_TopNExec[[Order[height{f}#1,ASC,LAST]],20[INTEGER],32] + \_ExchangeSourceExec[[_doc{f}#2, height{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver new file mode 100644 index 0000000000000..91fa3beaa5567 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver @@ -0,0 +1,17 @@ +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[_doc{f}#3, salary{f}#2, hire_date{f}#1]] + \_FieldExtractExec[salary{f}#2, hire_date{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query={ + "esql_single_value" : { + "field" : "salary", + "next" : { + "range" : { + "salary" : { + "gt" : 10000, + "boost" : 0.0 + } + } + }, + "source" : "salary > 10000@3:9" + } +}, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver new file mode 100644 index 0000000000000..1e90a18573c7c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver @@ -0,0 +1,6 @@ +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}#3, salary{f}#2, hire_date{f}#1]] +\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] + \_Filter[salary{f}#2 > 10000[INTEGER]] + \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver new file mode 100644 index 0000000000000..178d31ccc5dc1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0]<[],[]> + \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#3, salary{f}#2, hire_date{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver new file mode 100644 index 0000000000000..8dc76dd8b28df --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver @@ -0,0 +1,4 @@ +ExchangeSinkExec[[hire_date{f}#0, salary{f}#1],false] +\_ProjectExec[[_doc{f}#2, hire_date{f}#0]] + \_FieldExtractExec[hire_date{f}#0]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#2], limit[20], sort[[FieldSort[field=hire_date{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver new file mode 100644 index 0000000000000..070d12cb17d93 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[hire_date{f}#0, salary{f}#1],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}#2, hire_date{f}#0]] +\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#2, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#0, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#1, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver new file mode 100644 index 0000000000000..3c81025a6c14e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[hire_date{f}#0, salary{f}#1],false] +\_ProjectExec[[hire_date{f}#0, salary{f}#1]] + \_FieldExtractExec[salary{f}#1]<[],[]> + \_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],32] + \_ExchangeSourceExec[[_doc{f}#2, hire_date{f}#0],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver new file mode 100644 index 0000000000000..0280707cf7711 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver @@ -0,0 +1,4 @@ +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[_doc{f}#3, birth_date{r}#4 AS hire_date#1]] + \_EvalExec[[null[DATETIME] AS birth_date#4]] + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver new file mode 100644 index 0000000000000..fc4d011c9a8fb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[_doc{f}#3, hire_date{f}#1]] +\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver new file mode 100644 index 0000000000000..4b4fc0c891ac1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver @@ -0,0 +1,5 @@ +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> + \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file From 465826c516efec7e0c7c65fe7cd10aa5350aa591 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 3 Feb 2026 18:38:54 +0200 Subject: [PATCH 017/137] TEMP --- .../xpack/esql/core/expression/Alias.java | 2 +- .../xpack/esql/optimizer/GoldenTestCase.java | 14 +++++------ .../load/analysis.expected | 5 ++-- .../nullify/analysis.expected | 5 ++-- ...l_reduce_physical_optimization_data_driver | 4 --- .../local_reduce_planned_data_driver | 5 ---- .../local_reduce_planned_reduce_driver | 5 ---- ...l_reduce_physical_optimization_data_driver | 6 ----- .../local_reduce_planned_data_driver | 6 ----- .../local_reduce_planned_reduce_driver | 5 ---- ...l_reduce_physical_optimization_data_driver | 6 ----- .../local_reduce_planned_data_driver | 6 ----- .../local_reduce_planned_reduce_driver | 5 ---- ...l_reduce_physical_optimization_data_driver | 25 ------------------- .../local_reduce_planned_data_driver | 9 ------- .../local_reduce_planned_reduce_driver | 5 ---- ...l_reduce_physical_optimization_data_driver | 4 --- .../local_reduce_planned_data_driver | 5 ---- .../local_reduce_planned_reduce_driver | 5 ---- ...l_reduce_physical_optimization_data_driver | 4 --- .../local_reduce_planned_data_driver | 5 ---- .../local_reduce_planned_reduce_driver | 5 ---- ...l_reduce_physical_optimization_data_driver | 7 ------ ...reduce_physical_optimization_reduce_driver | 3 --- .../local_reduce_planned_data_driver | 7 ------ .../local_reduce_planned_reduce_driver | 3 --- ...l_reduce_physical_optimization_data_driver | 4 --- .../local_reduce_planned_data_driver | 5 ---- .../local_reduce_planned_reduce_driver | 5 ---- ...l_reduce_physical_optimization_data_driver | 17 ------------- .../local_reduce_planned_data_driver | 6 ----- .../local_reduce_planned_reduce_driver | 5 ---- ...l_reduce_physical_optimization_data_driver | 4 --- .../local_reduce_planned_data_driver | 5 ---- .../local_reduce_planned_reduce_driver | 5 ---- ...l_reduce_physical_optimization_data_driver | 4 --- .../local_reduce_planned_data_driver | 5 ---- .../local_reduce_planned_reduce_driver | 5 ---- 38 files changed, 12 insertions(+), 219 deletions(-) delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Alias.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Alias.java index 348374f7b174e..6e8b20f5a05a7 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Alias.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Alias.java @@ -143,7 +143,7 @@ public String toString() { @Override public String nodeString(NodeStringFormat format) { - return child.nodeString() + " AS " + name() + "#" + id(); + return child.nodeString(format) + " AS " + name() + "#" + id(); } /** diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 9044b2e9918dd..387da6f8f0824 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -278,7 +278,7 @@ private List> doTests() throws IOException { // If there is no local node-reduce physical optimization, there's nothing to verify! case DISABLED -> { var foo = localOptimize(reductionPlan.dataNodePlan(), conf); - var bar = verifyOrWrite(foo, outputPath(dualFileOutput.dataNodeOutput())); + var bar = verifyOrWrite(foo, expectedOutputPath(dualFileOutput.dataNodeOutput())); result.add(Tuple.tuple(Stage.NODE_REDUCE_LOCAL_PHYSICAL_OPTIMIZATION, bar)); } case ENABLED -> { @@ -323,8 +323,8 @@ private List> addDualPlanResult( String nodeReduceName, String dataNodeName ) throws IOException { - var reduceResult = verifyOrWrite(plan.nodeReducePlan(), outputPath(nodeReduceName)); - var dataResult = verifyOrWrite(plan.dataNodePlan(), outputPath(dataNodeName)); + var reduceResult = verifyOrWrite(plan.nodeReducePlan(), expectedOutputPath(nodeReduceName)); + var dataResult = verifyOrWrite(plan.dataNodePlan(), expectedOutputPath(dataNodeName)); var result = new ArrayList>(); if (reduceResult == TestResult.FAILURE || dataResult == TestResult.FAILURE) { result.add(Tuple.tuple(stage, TestResult.FAILURE)); @@ -343,7 +343,7 @@ private List> addDualPlanResult( } private > TestResult verifyOrWrite(T plan, Stage stage) throws IOException { - return verifyOrWrite(plan, stageOutputPath(stage)); + return verifyOrWrite(plan, expectedOutputPath(stage)); } private > TestResult verifyOrWrite(T plan, Path outputFile) throws IOException { @@ -360,11 +360,11 @@ private > TestResult verifyOrWrite(T plan, Path outputFil } } - private Path stageOutputPath(Stage stage) { - return stageOutputPath(((SingleFileOutput) stage.fileOutput).output()); + private Path expectedOutputPath(Stage stage) { + return expectedOutputPath(((SingleFileOutput) stage.fileOutput).output()); } - private Path stageOutputPath(String stageName) { + private Path expectedOutputPath(String stageName) { return outputPath(stageName + ".expected"); } diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected index 7a9858e13cc71..a4fbd276de29c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected @@ -1,4 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{f}#0) > 0[INTEGER] OR emp_no{f}#1 -5 > 0[INTEGER] OR TOLONG(does_not_exist2{f}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{f}#4)] AS c2#5]] - \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#8, first_name{f}#9, gender{f}#10, height{f}#11, height.float{f}#12, height.half_float{f}#13, height.scaled_float{f}#14, hire_date{f}#15, is_rehired{f}#16, job_positions{f}#17, languages{f}#18, languages.byte{f}#19, languages.long{f}#20, languages.short{f}#21, last_name{f}#22, salary{f}#23, salary_change{f}#24, salary_change.int{f}#25, salary_change.keyword{f}#26, salary_change.long{f}#27, still_hired{f}#28, does_not_exist1{f}#0, does_not_exist2{f}#2, does_not_exist3{f}#4] \ No newline at end of file +\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{f}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER] OR TOLONG(does_not_exist2{f}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{f}#4)] AS c2#5]] + \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#1, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27, does_not_exist1{f}#0, does_not_exist2{f}#2, does_not_exist3{f}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected index 1b1b5a8f9580e..6f8fec253f83b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected @@ -1,5 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{r}#0) > 0[INTEGER] OR emp_no{f}#1 -7 > 0[INTEGER] OR TOLONG(does_not_exist2{r}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{r}#4)] AS c2#5]] +\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{r}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER] OR TOLONG(does_not_exist2{r}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{r}#4)] AS c2#5]] \_Eval[[null[NULL] AS does_not_exist1#0, null[NULL] AS does_not_exist2#2, null[NULL] AS does_not_exist3#4]] - \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#8, first_name{f}#9, gender{f}#10, height{f}#11, height.float{f}#12, height.half_float{f}#13, height.scaled_float{f}#14, hire_date{f}#15, is_rehired{f}#16, job_positions{f}#17, languages{f}#18, languages.byte{f}#19, languages.long{f}#20, languages.short{f}#21, last_name{f}#22, salary{f}#23, salary_change{f}#24, salary_change.int{f}#25, salary_change.keyword{f}#26, salary_change.long{f}#27, still_hired{f}#28] \ No newline at end of file + \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#1, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver deleted file mode 100644 index 71c01677f83a5..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver +++ /dev/null @@ -1,4 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[_doc{f}#3, hire_date{f}#1]] - \_FieldExtractExec[hire_date{f}#1]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver deleted file mode 100644 index fc4d011c9a8fb..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#3, hire_date{f}#1]] -\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver deleted file mode 100644 index 4b4fc0c891ac1..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] - \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> - \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver deleted file mode 100644 index 8f49d89b830ce..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver +++ /dev/null @@ -1,6 +0,0 @@ -ExchangeSinkExec[[hire_date{f}#0, $$order_by$0{r}#1],false] -\_ProjectExec[[_doc{f}#2, $$order_by$0{r}#1]] - \_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],36] - \_EvalExec[[SIN(height{f}#3) * 2[INTEGER] AS $$order_by$0#1]] - \_FieldExtractExec[height{f}#3]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}#2], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver deleted file mode 100644 index 9ce3f748778c1..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver +++ /dev/null @@ -1,6 +0,0 @@ -ExchangeSinkExec[[hire_date{f}#0, $$order_by$0{r}#1],false] -\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#2, $$order_by$0{r}#1]] -\_TopN[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}#3) * 2[INTEGER] AS $$order_by$0#1]] - \_EsRelation[employees][_doc{f}#2, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#3, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#0, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver deleted file mode 100644 index d2459818c5588..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[hire_date{f}#0, $$order_by$0{r}#1],false] -\_ProjectExec[[hire_date{f}#0, $$order_by$0{r}#1]] - \_FieldExtractExec[hire_date{f}#0]<[],[]> - \_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#2, $$order_by$0{r}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver deleted file mode 100644 index 460cbcab3451e..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver +++ /dev/null @@ -1,6 +0,0 @@ -ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2],false] -\_ProjectExec[[_doc{f}#3, height{f}#0, $$order_by$0{r}#2]] - \_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],36] - \_EvalExec[[SIN(height{f}#0) * 2[INTEGER] AS $$order_by$0#2]] - \_FieldExtractExec[height{f}#0]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver deleted file mode 100644 index 932c4834e7e80..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver +++ /dev/null @@ -1,6 +0,0 @@ -ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2],false] -\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#3, height{f}#0, $$order_by$0{r}#2]] -\_TopN[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}#0) * 2[INTEGER] AS $$order_by$0#2]] - \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#0, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver deleted file mode 100644 index 88c85960c5dd2..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2],false] -\_ProjectExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2]] - \_FieldExtractExec[hire_date{f}#1]<[],[]> - \_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],44] - \_ExchangeSourceExec[[_doc{f}#3, height{f}#0, $$order_by$0{r}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver deleted file mode 100644 index ebbbae1cfcc6d..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver +++ /dev/null @@ -1,25 +0,0 @@ -ExchangeSinkExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] -\_ProjectExec[[_doc{f}#25, emp_no{f}#2, languages{f}#12, language_code{r}#23, language_name{f}#24]] - \_TopNExec[[Order[emp_no{f}#2,ASC,LAST]],20[INTEGER],82] - \_FieldExtractExec[emp_no{f}#2]<[],[]> - \_LookupJoinExec[[language_code{r}#23],[language_code{f}#26],[language_name{f}#24],null] - |_EvalExec[[languages{f}#12 AS language_code#23]] - | \_FieldExtractExec[languages{f}#12]<[],[]> - | \_EsQueryExec[employees], indexMode[standard], [_doc{f}#25], limit[], sort[] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query={ - "esql_single_value" : { - "field" : "emp_no", - "next" : { - "range" : { - "emp_no" : { - "gte" : 10091, - "lt" : 10094, - "time_zone" : "Z", - "boost" : 0.0 - } - } - }, - "source" : "emp_no >= 10091@4:9" - } -}, tags=[]]]] - \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -EsRelation[languages_lookup][LOOKUP][language_code{f}#26, language_name{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver deleted file mode 100644 index 7ff68ac134d83..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver +++ /dev/null @@ -1,9 +0,0 @@ -ExchangeSinkExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] -\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#25, emp_no{f}#2, languages{f}#12, language_code{r}#23, language_name{f}#24]] -\_TopN[[Order[emp_no{f}#2,ASC,LAST]],20[INTEGER],false] - \_Join[LEFT,[language_code{r}#23],[language_code{f}#26],null] - |_Eval[[languages{f}#12 AS language_code#23]] - | \_Filter[emp_no{f}#2 >= 10091[INTEGER] AND emp_no{f}#2 < 10094[INTEGER]] - | \_EsRelation[employees][_doc{f}#25, avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}#26, language_name{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver deleted file mode 100644 index 19c98b1780f37..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] -\_ProjectExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24]] - \_FieldExtractExec[avg_worked_seconds{f}#0, birth_date{f}#1, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<[],[]> - \_TopNExec[[Order[emp_no{f}#2,ASC,LAST]],20[INTEGER],430] - \_ExchangeSourceExec[[_doc{f}#25, emp_no{f}#2, languages{f}#12, language_code{r}#23, language_name{f}#24],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver deleted file mode 100644 index e5de0b72a7705..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver +++ /dev/null @@ -1,4 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2],false] -\_ProjectExec[[_doc{f}#3, hire_date{f}#2, height{f}#1]] - \_FieldExtractExec[hire_date{f}#2, height{f}#1]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#2, direction=ASC, nulls=LAST], FieldSort[field=height{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[32] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver deleted file mode 100644 index 4866ac15c30c3..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2],false] -\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#3, hire_date{f}#2, height{f}#1]] -\_TopN[[Order[hire_date{f}#2,ASC,LAST], Order[height{f}#1,ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#1, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#2, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver deleted file mode 100644 index ab96def3b448c..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2],false] -\_ProjectExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2]] - \_FieldExtractExec[emp_no{f}#0]<[],[]> - \_TopNExec[[Order[hire_date{f}#2,ASC,LAST], Order[height{f}#1,ASC,LAST]],20[INTEGER],40] - \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#2, height{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver deleted file mode 100644 index 71c01677f83a5..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver +++ /dev/null @@ -1,4 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[_doc{f}#3, hire_date{f}#1]] - \_FieldExtractExec[hire_date{f}#1]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver deleted file mode 100644 index fc4d011c9a8fb..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#3, hire_date{f}#1]] -\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver deleted file mode 100644 index 4b4fc0c891ac1..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] - \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> - \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver deleted file mode 100644 index f0d827b7d0c99..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver +++ /dev/null @@ -1,7 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2]] - \_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] - \_MvExpandExec[job_positions{f}#3,job_positions{r}#1] - \_ProjectExec[[emp_no{f}#0, job_positions{f}#3, salary{f}#2]] - \_FieldExtractExec[emp_no{f}#0, job_positions{f}#3, salary{f}#2]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}#4], limit[], sort[] estimatedRowSize[62] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver deleted file mode 100644 index a9639e399dec8..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver +++ /dev/null @@ -1,3 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] -\_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] - \_ExchangeSourceExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver deleted file mode 100644 index baf5e66932990..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver +++ /dev/null @@ -1,7 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] -\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#0, job_positions{r}#1, salary{f}#2]] -\_TopN[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],false] - \_MvExpand[job_positions{f}#3,job_positions{r}#1] - \_Project[[emp_no{f}#0, job_positions{f}#3, salary{f}#2]] - \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#3, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver deleted file mode 100644 index a9639e399dec8..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver +++ /dev/null @@ -1,3 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] -\_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] - \_ExchangeSourceExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver deleted file mode 100644 index cebf3f704c28d..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver +++ /dev/null @@ -1,4 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, height{f}#1],false] -\_ProjectExec[[_doc{f}#2, height{f}#1]] - \_FieldExtractExec[height{f}#1]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}#2], limit[20], sort[[FieldSort[field=height{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver deleted file mode 100644 index b2913dbdf505b..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, height{f}#1],false] -\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#2, height{f}#1]] -\_TopN[[Order[height{f}#1,ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}#2, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#0, first_name{f}#5, gender{f}#6, height{f}#1, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver deleted file mode 100644 index 3425364e715c1..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, height{f}#1],false] -\_ProjectExec[[emp_no{f}#0, height{f}#1]] - \_FieldExtractExec[emp_no{f}#0]<[],[]> - \_TopNExec[[Order[height{f}#1,ASC,LAST]],20[INTEGER],32] - \_ExchangeSourceExec[[_doc{f}#2, height{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver deleted file mode 100644 index 91fa3beaa5567..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver +++ /dev/null @@ -1,17 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[_doc{f}#3, salary{f}#2, hire_date{f}#1]] - \_FieldExtractExec[salary{f}#2, hire_date{f}#1]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query={ - "esql_single_value" : { - "field" : "salary", - "next" : { - "range" : { - "salary" : { - "gt" : 10000, - "boost" : 0.0 - } - } - }, - "source" : "salary > 10000@3:9" - } -}, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver deleted file mode 100644 index 1e90a18573c7c..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver +++ /dev/null @@ -1,6 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#3, salary{f}#2, hire_date{f}#1]] -\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] - \_Filter[salary{f}#2 > 10000[INTEGER]] - \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver deleted file mode 100644 index 178d31ccc5dc1..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] - \_FieldExtractExec[emp_no{f}#0]<[],[]> - \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#3, salary{f}#2, hire_date{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver deleted file mode 100644 index 8dc76dd8b28df..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver +++ /dev/null @@ -1,4 +0,0 @@ -ExchangeSinkExec[[hire_date{f}#0, salary{f}#1],false] -\_ProjectExec[[_doc{f}#2, hire_date{f}#0]] - \_FieldExtractExec[hire_date{f}#0]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}#2], limit[20], sort[[FieldSort[field=hire_date{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver deleted file mode 100644 index 070d12cb17d93..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[hire_date{f}#0, salary{f}#1],false] -\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#2, hire_date{f}#0]] -\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}#2, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#0, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#1, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver deleted file mode 100644 index 3c81025a6c14e..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[hire_date{f}#0, salary{f}#1],false] -\_ProjectExec[[hire_date{f}#0, salary{f}#1]] - \_FieldExtractExec[salary{f}#1]<[],[]> - \_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],32] - \_ExchangeSourceExec[[_doc{f}#2, hire_date{f}#0],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver deleted file mode 100644 index 0280707cf7711..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver +++ /dev/null @@ -1,4 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[_doc{f}#3, birth_date{r}#4 AS hire_date#1]] - \_EvalExec[[null[DATETIME] AS birth_date#4]] - \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver deleted file mode 100644 index fc4d011c9a8fb..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#3, hire_date{f}#1]] -\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver deleted file mode 100644 index 4b4fc0c891ac1..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver +++ /dev/null @@ -1,5 +0,0 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] - \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> - \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file From 4c8ae6353663a75e9e3c6893a5267bd8e3d36f94 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 3 Feb 2026 21:16:52 +0200 Subject: [PATCH 018/137] Added more tests --- .../analysis/AnalyzerUnmappedGoldenTests.java | 110 +++++++++++++++++- .../testCoalesce/load/analysis.expected | 4 + .../testCoalesce/load/query.esql | 3 + .../testCoalesce/nullify/analysis.expected | 5 + .../testCoalesce/nullify/query.esql | 3 + .../testFork/load/analysis.expected | 13 +++ .../testFork/load/query.esql | 3 + .../testFork/nullify/analysis.expected | 14 +++ .../testFork/nullify/query.esql | 3 + .../testForkWithEval/load/analysis.expected | 14 +++ .../testForkWithEval/load/query.esql | 3 + .../nullify/analysis.expected | 15 +++ .../testForkWithEval/nullify/query.esql | 3 + .../testForkWithSort/load/analysis.expected | 19 +++ .../testForkWithSort/load/query.esql | 4 + .../nullify/analysis.expected | 21 ++++ .../testForkWithSort/nullify/query.esql | 4 + .../testForkWithStats/load/analysis.expected | 15 +++ .../testForkWithStats/load/query.esql | 4 + .../nullify/analysis.expected | 16 +++ .../testForkWithStats/nullify/query.esql | 4 + .../testLookupJoin/load/analysis.expected | 5 + .../testLookupJoin/load/query.esql | 3 + .../testLookupJoin/nullify/analysis.expected | 6 + .../testLookupJoin/nullify/query.esql | 3 + .../load/analysis.expected | 6 + .../testLookupJoinWithEval/load/query.esql | 4 + .../nullify/analysis.expected | 7 ++ .../testLookupJoinWithEval/nullify/query.esql | 4 + .../load/analysis.expected | 6 + .../testLookupJoinWithFilter/load/query.esql | 4 + .../nullify/analysis.expected | 7 ++ .../nullify/query.esql | 4 + .../testSubquery/load/analysis.expected | 11 ++ .../testSubquery/load/query.esql | 2 + .../testSubquery/nullify/analysis.expected | 12 ++ .../testSubquery/nullify/query.esql | 2 + .../load/analysis.expected | 11 ++ .../load/query.esql | 3 + .../nullify/analysis.expected | 12 ++ .../nullify/query.esql | 3 + .../load/analysis.expected | 11 ++ .../testSubqueryKeepUnmapped/load/query.esql | 2 + .../nullify/analysis.expected | 12 ++ .../nullify/query.esql | 2 + .../load/analysis.expected | 21 ++++ .../load/query.esql | 5 + .../nullify/analysis.expected | 23 ++++ .../nullify/query.esql | 5 + .../load/analysis.expected | 11 ++ .../testSubqueryWithStats/load/query.esql | 2 + .../nullify/analysis.expected | 12 ++ .../testSubqueryWithStats/nullify/query.esql | 2 + .../testTBucket/load/analysis.expected | 4 + .../testTBucket/load/query.esql | 3 + .../testTBucket/nullify/analysis.expected | 5 + .../testTBucket/nullify/query.esql | 3 + .../load/analysis.expected | 3 + .../load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../load/analysis.expected | 4 + .../testTimeSeriesAvgOverTime/load/query.esql | 3 + .../nullify/analysis.expected | 5 + .../nullify/query.esql | 3 + .../load/analysis.expected | 4 + .../load/query.esql | 3 + .../nullify/analysis.expected | 5 + .../nullify/query.esql | 3 + .../load/analysis.expected | 3 + .../load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../load/analysis.expected | 4 + .../testTimeSeriesMaxOverTime/load/query.esql | 3 + .../nullify/analysis.expected | 5 + .../nullify/query.esql | 3 + .../testTimeSeriesRate/load/analysis.expected | 4 + .../testTimeSeriesRate/load/query.esql | 3 + .../nullify/analysis.expected | 5 + .../testTimeSeriesRate/nullify/query.esql | 3 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../nullify/query.esql | 2 + 96 files changed, 638 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateWithUnmappedGroupBy/nullify/query.esql diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java index e1de3ba5bf151..ce64011cdcb6c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -263,6 +263,106 @@ public void testMvExpand() throws Exception { """); } + public void testLookupJoin() throws Exception { + runTests(""" + FROM employees + | EVAL language_code = does_not_exist::INTEGER + | LOOKUP JOIN languages_lookup ON language_code + """); + } + + public void testLookupJoinWithFilter() throws Exception { + runTests(""" + FROM employees + | EVAL language_code = languages + | LOOKUP JOIN languages_lookup ON language_code + | WHERE does_not_exist::LONG > 0 + """); + } + + public void testSubqueryKeepUnmapped() throws Exception { + runTests(""" + FROM employees, (FROM languages | KEEP language_code, does_not_exist) + | KEEP emp_no, language_code, does_not_exist + """); + } + + public void testSubqueryWithStats() throws Exception { + runTests(""" + FROM employees, (FROM sample_data | STATS max_ts = MAX(@timestamp) BY does_not_exist) + | KEEP emp_no, max_ts, does_not_exist + """); + } + + public void testSubqueryKeepMultipleUnmapped() throws Exception { + runTests(""" + FROM employees, + (FROM languages | KEEP language_code, unmapped1, unmapped2) + | KEEP emp_no, language_code, unmapped1, unmapped2 + """); + } + + public void testFork() throws Exception { + runTests(""" + FROM employees + | FORK (WHERE does_not_exist::LONG > 0) + (WHERE emp_no > 0) + """); + } + + public void testForkWithEval() throws Exception { + runTests(""" + FROM employees + | FORK (EVAL x = does_not_exist::DOUBLE + 1) + (EVAL y = emp_no + 1) + """); + } + + public void testForkWithStats() throws Exception { + runTests(""" + FROM employees + | FORK (STATS c = COUNT(*) BY does_not_exist) + (STATS d = AVG(salary::DOUBLE)) + | SORT does_not_exist + """); + } + + public void testCoalesce() throws Exception { + runTests(""" + FROM employees + | EVAL x = COALESCE(does_not_exist::LONG, emp_no, 0) + | KEEP emp_no, x + """); + } + + public void testTBucketGroupByUnmapped() throws Exception { + runTests(""" + FROM sample_data + | STATS c = COUNT(*) BY tbucket(1 hour), does_not_exist + """); + } + + public void testTBucketAggregateUnmapped() throws Exception { + runTests(""" + FROM sample_data + | STATS s = SUM(does_not_exist::DOUBLE), c = COUNT(*) BY tbucket(1 day) + """); + } + + public void testTimeSeriesRateUnmapped() throws Exception { + runTestsNullifyOnly(""" + TS k8s + | STATS r = RATE(does_not_exist) BY tbucket(1 hour) + """); + } + + public void testTimeSeriesFirstOverTimeUnmapped() throws Exception { + runTests(""" + TS k8s + | STATS f = FIRST_OVER_TIME(does_not_exist::DOUBLE) BY tbucket(1 hour) + """); + } + @Override protected java.util.List filteredWarnings() { return withDefaultLimitWarning(super.filteredWarnings()); @@ -277,11 +377,15 @@ private static String setUnmappedLoad(String query) { } private void runTests(String query) { - if (EsqlCapabilities.Cap.OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW.isEnabled()) { - builder(setUnmappedNullify(query)).nestedPath("nullify").stages(STAGES).run(); - } + runTestsNullifyOnly(query); if (EsqlCapabilities.Cap.OPTIONAL_FIELDS.isEnabled()) { builder(setUnmappedLoad(query)).nestedPath("load").stages(STAGES).run(); } } + + private void runTestsNullifyOnly(String query) { + if (EsqlCapabilities.Cap.OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW.isEnabled()) { + builder(setUnmappedNullify(query)).nestedPath("nullify").stages(STAGES).run(); + } + } } diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/analysis.expected new file mode 100644 index 0000000000000..d3111b5b4cda6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{f}#0, x{r}#1]] + \_Eval[[COALESCE(TOLONG(does_not_exist{f}#2),TOLONG(emp_no{f}#0),TOLONG(0[INTEGER])) AS x#1]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#0, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist{f}#2, x{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/query.esql new file mode 100644 index 0000000000000..fffcba043eaeb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| EVAL x = COALESCE(does_not_exist::LONG, emp_no, 0) +| KEEP emp_no, x diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/analysis.expected new file mode 100644 index 0000000000000..5cccb49a752cc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{f}#0, x{r}#1]] + \_Eval[[COALESCE(TOLONG(does_not_exist{r}#2),TOLONG(emp_no{f}#0),TOLONG(0[INTEGER])) AS x#1]] + \_Eval[[null[NULL] AS does_not_exist#2, null[NULL] AS x#3]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/query.esql new file mode 100644 index 0000000000000..7de1ffe56d169 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL x = COALESCE(does_not_exist::LONG, emp_no, 0) +| KEEP emp_no, x diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected new file mode 100644 index 0000000000000..8c02caed8fa2b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected @@ -0,0 +1,13 @@ +Limit[1000[INTEGER],false,false] +\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, _fork{r}#24]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, does_not_exist{f}#48, _fork{r}#49]] + | \_Eval[[fork1[KEYWORD] AS _fork#49]] + | \_Filter[TOLONG(does_not_exist{f}#48) > 0[INTEGER]] + | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, does_not_exist{f}#48] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f}#50, birth_date{f}#51, emp_no{f}#52, first_name{f}#53, gender{f}#54, height{f}#55, height.float{f}#56, height.half_float{f}#57, height.scaled_float{f}#58, hire_date{f}#59, is_rehired{f}#60, job_positions{f}#61, languages{f}#62, languages.byte{f}#63, languages.long{f}#64, languages.short{f}#65, last_name{f}#66, salary{f}#67, salary_change{f}#68, salary_change.int{f}#69, salary_change.keyword{f}#70, salary_change.long{f}#71, still_hired{f}#72, does_not_exist{r}#73, _fork{r}#49]] + \_Eval[[null[KEYWORD] AS does_not_exist#73]] + \_Eval[[fork2[KEYWORD] AS _fork#49]] + \_Filter[emp_no{f}#52 > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#50, birth_date{f}#51, emp_no{f}#52, first_name{f}#53, gender{f}#54, height{f}#55, height.float{f}#56, height.half_float{f}#57, height.scaled_float{f}#58, hire_date{f}#59, is_rehired{f}#60, job_positions{f}#61, languages{f}#62, languages.byte{f}#63, languages.long{f}#64, languages.short{f}#65, last_name{f}#66, salary{f}#67, salary_change{f}#68, salary_change.int{f}#69, salary_change.keyword{f}#70, salary_change.long{f}#71, still_hired{f}#72] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql new file mode 100644 index 0000000000000..1b2a31d2f6afd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| FORK (WHERE does_not_exist::LONG > 0) + (WHERE emp_no > 0) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/analysis.expected new file mode 100644 index 0000000000000..126b23315f762 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/analysis.expected @@ -0,0 +1,14 @@ +Limit[1000[INTEGER],false,false] +\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, _fork{r}#24]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, does_not_exist{r}#48, _fork{r}#49]] + | \_Eval[[fork1[KEYWORD] AS _fork#49]] + | \_Filter[TOLONG(does_not_exist{r}#48) > 0[INTEGER]] + | \_Eval[[null[NULL] AS does_not_exist#48]] + | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f}#50, birth_date{f}#51, emp_no{f}#52, first_name{f}#53, gender{f}#54, height{f}#55, height.float{f}#56, height.half_float{f}#57, height.scaled_float{f}#58, hire_date{f}#59, is_rehired{f}#60, job_positions{f}#61, languages{f}#62, languages.byte{f}#63, languages.long{f}#64, languages.short{f}#65, last_name{f}#66, salary{f}#67, salary_change{f}#68, salary_change.int{f}#69, salary_change.keyword{f}#70, salary_change.long{f}#71, still_hired{f}#72, does_not_exist{r}#73, _fork{r}#49]] + \_Eval[[null[NULL] AS does_not_exist#73]] + \_Eval[[fork2[KEYWORD] AS _fork#49]] + \_Filter[emp_no{f}#52 > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#50, birth_date{f}#51, emp_no{f}#52, first_name{f}#53, gender{f}#54, height{f}#55, height.float{f}#56, height.half_float{f}#57, height.scaled_float{f}#58, hire_date{f}#59, is_rehired{f}#60, job_positions{f}#61, languages{f}#62, languages.byte{f}#63, languages.long{f}#64, languages.short{f}#65, last_name{f}#66, salary{f}#67, salary_change{f}#68, salary_change.int{f}#69, salary_change.keyword{f}#70, salary_change.long{f}#71, still_hired{f}#72] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/query.esql new file mode 100644 index 0000000000000..f52a0ffff2847 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| FORK (WHERE does_not_exist::LONG > 0) + (WHERE emp_no > 0) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected new file mode 100644 index 0000000000000..96d5b43c3eb3b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected @@ -0,0 +1,14 @@ +Limit[1000[INTEGER],false,false] +\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, x{r}#24, _fork{r}#25, y{r}#26]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, does_not_exist{f}#50, x{r}#51, _fork{r}#52, y{r}#53]] + | \_Eval[[null[INTEGER] AS y#53]] + | \_Eval[[fork1[KEYWORD] AS _fork#52]] + | \_Eval[[TODOUBLE(does_not_exist{f}#50) + 1[INTEGER] AS x#51]] + | \_EsRelation[employees][avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, does_not_exist{f}#50] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f}#54, birth_date{f}#55, emp_no{f}#56, first_name{f}#57, gender{f}#58, height{f}#59, height.float{f}#60, height.half_float{f}#61, height.scaled_float{f}#62, hire_date{f}#63, is_rehired{f}#64, job_positions{f}#65, languages{f}#66, languages.byte{f}#67, languages.long{f}#68, languages.short{f}#69, last_name{f}#70, salary{f}#71, salary_change{f}#72, salary_change.int{f}#73, salary_change.keyword{f}#74, salary_change.long{f}#75, still_hired{f}#76, does_not_exist{r}#77, x{r}#78, _fork{r}#52, y{r}#79]] + \_Eval[[null[KEYWORD] AS does_not_exist#77, null[DOUBLE] AS x#78]] + \_Eval[[fork2[KEYWORD] AS _fork#52]] + \_Eval[[emp_no{f}#56 + 1[INTEGER] AS y#79]] + \_EsRelation[employees][avg_worked_seconds{f}#54, birth_date{f}#55, emp_no{f}#56, first_name{f}#57, gender{f}#58, height{f}#59, height.float{f}#60, height.half_float{f}#61, height.scaled_float{f}#62, hire_date{f}#63, is_rehired{f}#64, job_positions{f}#65, languages{f}#66, languages.byte{f}#67, languages.long{f}#68, languages.short{f}#69, last_name{f}#70, salary{f}#71, salary_change{f}#72, salary_change.int{f}#73, salary_change.keyword{f}#74, salary_change.long{f}#75, still_hired{f}#76] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql new file mode 100644 index 0000000000000..f007f2dec96ca --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| FORK (EVAL x = does_not_exist::DOUBLE + 1) + (EVAL y = emp_no + 1) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/analysis.expected new file mode 100644 index 0000000000000..745bf77c8febb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/analysis.expected @@ -0,0 +1,15 @@ +Limit[1000[INTEGER],false,false] +\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, x{r}#24, _fork{r}#25, y{r}#26]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, does_not_exist{r}#50, x{r}#51, _fork{r}#52, y{r}#53]] + | \_Eval[[null[INTEGER] AS y#53]] + | \_Eval[[fork1[KEYWORD] AS _fork#52]] + | \_Eval[[TODOUBLE(does_not_exist{r}#50) + 1[INTEGER] AS x#51]] + | \_Eval[[null[NULL] AS does_not_exist#50]] + | \_EsRelation[employees][avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f}#54, birth_date{f}#55, emp_no{f}#56, first_name{f}#57, gender{f}#58, height{f}#59, height.float{f}#60, height.half_float{f}#61, height.scaled_float{f}#62, hire_date{f}#63, is_rehired{f}#64, job_positions{f}#65, languages{f}#66, languages.byte{f}#67, languages.long{f}#68, languages.short{f}#69, last_name{f}#70, salary{f}#71, salary_change{f}#72, salary_change.int{f}#73, salary_change.keyword{f}#74, salary_change.long{f}#75, still_hired{f}#76, does_not_exist{r}#77, x{r}#78, _fork{r}#52, y{r}#79]] + \_Eval[[null[NULL] AS does_not_exist#77, null[DOUBLE] AS x#78]] + \_Eval[[fork2[KEYWORD] AS _fork#52]] + \_Eval[[emp_no{f}#56 + 1[INTEGER] AS y#79]] + \_EsRelation[employees][avg_worked_seconds{f}#54, birth_date{f}#55, emp_no{f}#56, first_name{f}#57, gender{f}#58, height{f}#59, height.float{f}#60, height.half_float{f}#61, height.scaled_float{f}#62, hire_date{f}#63, is_rehired{f}#64, job_positions{f}#65, languages{f}#66, languages.byte{f}#67, languages.long{f}#68, languages.short{f}#69, last_name{f}#70, salary{f}#71, salary_change{f}#72, salary_change.int{f}#73, salary_change.keyword{f}#74, salary_change.long{f}#75, still_hired{f}#76] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/query.esql new file mode 100644 index 0000000000000..70e809476f257 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| FORK (EVAL x = does_not_exist::DOUBLE + 1) + (EVAL y = emp_no + 1) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/analysis.expected new file mode 100644 index 0000000000000..466d405f796e8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/analysis.expected @@ -0,0 +1,19 @@ +Limit[10000[INTEGER],false,false] +\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist1{r}#23, does_not_exist2{r}#24, _fork{r}#25, does_not_exist3{r}#26, xyz{r}#27]] + |_Limit[10000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f}#28, birth_date{f}#29, emp_no{f}#30, first_name{f}#31, gender{f}#32, height{f}#33, height.float{f}#34, height.half_float{f}#35, height.scaled_float{f}#36, hire_date{f}#37, is_rehired{f}#38, job_positions{f}#39, languages{f}#40, languages.byte{f}#41, languages.long{f}#42, languages.short{f}#43, last_name{f}#44, salary{f}#45, salary_change{f}#46, salary_change.int{f}#47, salary_change.keyword{f}#48, salary_change.long{f}#49, still_hired{f}#50, does_not_exist1{f}#51, does_not_exist2{f}#52, _fork{r}#53, does_not_exist3{r}#54, xyz{r}#55]] + | \_Eval[[null[KEYWORD] AS does_not_exist3#54, null[KEYWORD] AS xyz#55]] + | \_Eval[[fork1[KEYWORD] AS _fork#53]] + | \_Limit[7[INTEGER],false,false] + | \_OrderBy[[Order[does_not_exist2{f}#52,ASC,LAST]]] + | \_Filter[emp_no{f}#30 > 3[INTEGER]] + | \_Filter[TOLONG(does_not_exist1{f}#51) > 5[INTEGER]] + | \_EsRelation[employees][avg_worked_seconds{f}#28, birth_date{f}#29, emp_no{f}#30, first_name{f}#31, gender{f}#32, height{f}#33, height.float{f}#34, height.half_float{f}#35, height.scaled_float{f}#36, hire_date{f}#37, is_rehired{f}#38, job_positions{f}#39, languages{f}#40, languages.byte{f}#41, languages.long{f}#42, languages.short{f}#43, last_name{f}#44, salary{f}#45, salary_change{f}#46, salary_change.int{f}#47, salary_change.keyword{f}#48, salary_change.long{f}#49, still_hired{f}#50, does_not_exist1{f}#51, does_not_exist2{f}#52] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f}#56, birth_date{f}#57, emp_no{f}#58, first_name{f}#59, gender{f}#60, height{f}#61, height.float{f}#62, height.half_float{f}#63, height.scaled_float{f}#64, hire_date{f}#65, is_rehired{f}#66, job_positions{f}#67, languages{f}#68, languages.byte{f}#69, languages.long{f}#70, languages.short{f}#71, last_name{f}#72, salary{f}#73, salary_change{f}#74, salary_change.int{f}#75, salary_change.keyword{f}#76, salary_change.long{f}#77, still_hired{f}#78, does_not_exist1{f}#79, does_not_exist2{r}#80, _fork{r}#53, does_not_exist3{f}#81, xyz{r}#82]] + \_Eval[[null[KEYWORD] AS does_not_exist2#80]] + \_Eval[[fork2[KEYWORD] AS _fork#53]] + \_Eval[[TOSTRING(does_not_exist3{f}#81) AS xyz#82]] + \_Filter[emp_no{f}#58 > 2[INTEGER]] + \_Filter[TOLONG(does_not_exist1{f}#79) > 5[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#56, birth_date{f}#57, emp_no{f}#58, first_name{f}#59, gender{f}#60, height{f}#61, height.float{f}#62, height.half_float{f}#63, height.scaled_float{f}#64, hire_date{f}#65, is_rehired{f}#66, job_positions{f}#67, languages{f}#68, languages.byte{f}#69, languages.long{f}#70, languages.short{f}#71, last_name{f}#72, salary{f}#73, salary_change{f}#74, salary_change.int{f}#75, salary_change.keyword{f}#76, salary_change.long{f}#77, still_hired{f}#78, does_not_exist1{f}#79, does_not_exist3{f}#81] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/query.esql new file mode 100644 index 0000000000000..27269779f68d7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees +| WHERE does_not_exist1::LONG > 5 +| FORK (WHERE emp_no > 3 | SORT does_not_exist2 | LIMIT 7) + (WHERE emp_no > 2 | EVAL xyz = does_not_exist3::KEYWORD) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/analysis.expected new file mode 100644 index 0000000000000..99494fb1c5fff --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/analysis.expected @@ -0,0 +1,21 @@ +Limit[10000[INTEGER],false,false] +\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist1{r}#23, does_not_exist2{r}#24, _fork{r}#25, does_not_exist3{r}#26, xyz{r}#27]] + |_Limit[10000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f}#28, birth_date{f}#29, emp_no{f}#30, first_name{f}#31, gender{f}#32, height{f}#33, height.float{f}#34, height.half_float{f}#35, height.scaled_float{f}#36, hire_date{f}#37, is_rehired{f}#38, job_positions{f}#39, languages{f}#40, languages.byte{f}#41, languages.long{f}#42, languages.short{f}#43, last_name{f}#44, salary{f}#45, salary_change{f}#46, salary_change.int{f}#47, salary_change.keyword{f}#48, salary_change.long{f}#49, still_hired{f}#50, does_not_exist1{r}#51, does_not_exist2{r}#52, _fork{r}#53, does_not_exist3{r}#54, xyz{r}#55]] + | \_Eval[[null[NULL] AS does_not_exist3#54, null[KEYWORD] AS xyz#55]] + | \_Eval[[fork1[KEYWORD] AS _fork#53]] + | \_Limit[7[INTEGER],false,false] + | \_OrderBy[[Order[does_not_exist2{r}#52,ASC,LAST]]] + | \_Filter[emp_no{f}#30 > 3[INTEGER]] + | \_Filter[TOLONG(does_not_exist1{r}#51) > 5[INTEGER]] + | \_Eval[[null[NULL] AS does_not_exist1#51, null[NULL] AS does_not_exist2#52]] + | \_EsRelation[employees][avg_worked_seconds{f}#28, birth_date{f}#29, emp_no{f}#30, first_name{f}#31, gender{f}#32, height{f}#33, height.float{f}#34, height.half_float{f}#35, height.scaled_float{f}#36, hire_date{f}#37, is_rehired{f}#38, job_positions{f}#39, languages{f}#40, languages.byte{f}#41, languages.long{f}#42, languages.short{f}#43, last_name{f}#44, salary{f}#45, salary_change{f}#46, salary_change.int{f}#47, salary_change.keyword{f}#48, salary_change.long{f}#49, still_hired{f}#50] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f}#56, birth_date{f}#57, emp_no{f}#58, first_name{f}#59, gender{f}#60, height{f}#61, height.float{f}#62, height.half_float{f}#63, height.scaled_float{f}#64, hire_date{f}#65, is_rehired{f}#66, job_positions{f}#67, languages{f}#68, languages.byte{f}#69, languages.long{f}#70, languages.short{f}#71, last_name{f}#72, salary{f}#73, salary_change{f}#74, salary_change.int{f}#75, salary_change.keyword{f}#76, salary_change.long{f}#77, still_hired{f}#78, does_not_exist1{r}#79, does_not_exist2{r}#80, _fork{r}#53, does_not_exist3{r}#81, xyz{r}#82]] + \_Eval[[null[NULL] AS does_not_exist2#80]] + \_Eval[[fork2[KEYWORD] AS _fork#53]] + \_Eval[[TOSTRING(does_not_exist3{r}#81) AS xyz#82]] + \_Filter[emp_no{f}#58 > 2[INTEGER]] + \_Filter[TOLONG(does_not_exist1{r}#79) > 5[INTEGER]] + \_Eval[[null[NULL] AS does_not_exist1#79, null[NULL] AS does_not_exist3#81]] + \_EsRelation[employees][avg_worked_seconds{f}#56, birth_date{f}#57, emp_no{f}#58, first_name{f}#59, gender{f}#60, height{f}#61, height.float{f}#62, height.half_float{f}#63, height.scaled_float{f}#64, hire_date{f}#65, is_rehired{f}#66, job_positions{f}#67, languages{f}#68, languages.byte{f}#69, languages.long{f}#70, languages.short{f}#71, last_name{f}#72, salary{f}#73, salary_change{f}#74, salary_change.int{f}#75, salary_change.keyword{f}#76, salary_change.long{f}#77, still_hired{f}#78] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/query.esql new file mode 100644 index 0000000000000..c843b72d7d898 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees +| WHERE does_not_exist1::LONG > 5 +| FORK (WHERE emp_no > 3 | SORT does_not_exist2 | LIMIT 7) + (WHERE emp_no > 2 | EVAL xyz = does_not_exist3::KEYWORD) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected new file mode 100644 index 0000000000000..179c4819647d5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected @@ -0,0 +1,15 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[does_not_exist{r}#0,ASC,LAST]]] + \_Fork[[c{r}#1, does_not_exist{r}#0, _fork{r}#2, d{r}#3]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[c{r}#4, does_not_exist{f}#5, _fork{r}#6, d{r}#7]] + | \_Eval[[null[DOUBLE] AS d#7]] + | \_Eval[[fork1[KEYWORD] AS _fork#6]] + | \_Aggregate[[does_not_exist{f}#5],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist{f}#5]] + | \_EsRelation[employees][avg_worked_seconds{f}#8, birth_date{f}#9, emp_no{f}#10, first_name{f}#11, gender{f}#12, height{f}#13, height.float{f}#14, height.half_float{f}#15, height.scaled_float{f}#16, hire_date{f}#17, is_rehired{f}#18, job_positions{f}#19, languages{f}#20, languages.byte{f}#21, languages.long{f}#22, languages.short{f}#23, last_name{f}#24, salary{f}#25, salary_change{f}#26, salary_change.int{f}#27, salary_change.keyword{f}#28, salary_change.long{f}#29, still_hired{f}#30, does_not_exist{f}#5] + \_Limit[1000[INTEGER],false,false] + \_Project[[c{r}#31, does_not_exist{r}#32, _fork{r}#6, d{r}#33]] + \_Eval[[null[LONG] AS c#31, null[KEYWORD] AS does_not_exist#32]] + \_Eval[[fork2[KEYWORD] AS _fork#6]] + \_Aggregate[[],[AVG(TODOUBLE(salary{f}#34),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS d#33]] + \_EsRelation[employees][avg_worked_seconds{f}#35, birth_date{f}#36, emp_no{f}#37, first_name{f}#38, gender{f}#39, height{f}#40, height.float{f}#41, height.half_float{f}#42, height.scaled_float{f}#43, hire_date{f}#44, is_rehired{f}#45, job_positions{f}#46, languages{f}#47, languages.byte{f}#48, languages.long{f}#49, languages.short{f}#50, last_name{f}#51, salary{f}#34, salary_change{f}#52, salary_change.int{f}#53, salary_change.keyword{f}#54, salary_change.long{f}#55, still_hired{f}#56] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql new file mode 100644 index 0000000000000..3a52496cdfc84 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees +| FORK (STATS c = COUNT(*) BY does_not_exist) + (STATS d = AVG(salary::DOUBLE)) +| SORT does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/analysis.expected new file mode 100644 index 0000000000000..0905fb72ef867 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/analysis.expected @@ -0,0 +1,16 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[does_not_exist{r}#0,ASC,LAST]]] + \_Fork[[c{r}#1, does_not_exist{r}#0, _fork{r}#2, d{r}#3]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[c{r}#4, does_not_exist{r}#5, _fork{r}#6, d{r}#7]] + | \_Eval[[null[DOUBLE] AS d#7]] + | \_Eval[[fork1[KEYWORD] AS _fork#6]] + | \_Aggregate[[does_not_exist{r}#5],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist{r}#5]] + | \_Eval[[null[NULL] AS does_not_exist#5]] + | \_EsRelation[employees][avg_worked_seconds{f}#8, birth_date{f}#9, emp_no{f}#10, first_name{f}#11, gender{f}#12, height{f}#13, height.float{f}#14, height.half_float{f}#15, height.scaled_float{f}#16, hire_date{f}#17, is_rehired{f}#18, job_positions{f}#19, languages{f}#20, languages.byte{f}#21, languages.long{f}#22, languages.short{f}#23, last_name{f}#24, salary{f}#25, salary_change{f}#26, salary_change.int{f}#27, salary_change.keyword{f}#28, salary_change.long{f}#29, still_hired{f}#30] + \_Limit[1000[INTEGER],false,false] + \_Project[[c{r}#31, does_not_exist{r}#32, _fork{r}#6, d{r}#33]] + \_Eval[[null[LONG] AS c#31, null[NULL] AS does_not_exist#32]] + \_Eval[[fork2[KEYWORD] AS _fork#6]] + \_Aggregate[[],[AVG(TODOUBLE(salary{f}#34),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS d#33]] + \_EsRelation[employees][avg_worked_seconds{f}#35, birth_date{f}#36, emp_no{f}#37, first_name{f}#38, gender{f}#39, height{f}#40, height.float{f}#41, height.half_float{f}#42, height.scaled_float{f}#43, hire_date{f}#44, is_rehired{f}#45, job_positions{f}#46, languages{f}#47, languages.byte{f}#48, languages.long{f}#49, languages.short{f}#50, last_name{f}#51, salary{f}#34, salary_change{f}#52, salary_change.int{f}#53, salary_change.keyword{f}#54, salary_change.long{f}#55, still_hired{f}#56] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/query.esql new file mode 100644 index 0000000000000..e6d155e05a41b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees +| FORK (STATS c = COUNT(*) BY does_not_exist) + (STATS d = AVG(salary::DOUBLE)) +| SORT does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected new file mode 100644 index 0000000000000..f57fe6df9c0a7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_LookupJoin[LEFT,[language_code{r}#0],[language_code{f}#1],false,null] + |_Eval[[TOINTEGER(does_not_exist{f}#2) AS language_code#0]] + | \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#2] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#1, language_name{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql new file mode 100644 index 0000000000000..4297a1b213923 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| EVAL language_code = does_not_exist::INTEGER +| LOOKUP JOIN languages_lookup ON language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/analysis.expected new file mode 100644 index 0000000000000..8a2b4eaf82e13 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/analysis.expected @@ -0,0 +1,6 @@ +Limit[1000[INTEGER],false,false] +\_LookupJoin[LEFT,[language_code{r}#0],[language_code{f}#1],false,null] + |_Eval[[TOINTEGER(does_not_exist{r}#2) AS language_code#0]] + | \_Eval[[null[NULL] AS does_not_exist#2]] + | \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#1, language_name{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/query.esql new file mode 100644 index 0000000000000..e0f372f5ca05b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL language_code = does_not_exist::INTEGER +| LOOKUP JOIN languages_lookup ON language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/analysis.expected new file mode 100644 index 0000000000000..3feb294dd5dc4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/analysis.expected @@ -0,0 +1,6 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(does_not_exist{f}#0) + 1[INTEGER] AS x#1]] + \_LookupJoin[LEFT,[language_code{r}#2],[language_code{f}#3],false,null] + |_Eval[[languages{f}#4 AS language_code#2]] + | \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#7, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#4, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26, does_not_exist{f}#0] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#3, language_name{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/query.esql new file mode 100644 index 0000000000000..787070f352209 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees +| EVAL language_code = languages +| LOOKUP JOIN languages_lookup ON language_code +| EVAL x = does_not_exist::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/analysis.expected new file mode 100644 index 0000000000000..de08464ba34a8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/analysis.expected @@ -0,0 +1,7 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(does_not_exist{r}#0) + 1[INTEGER] AS x#1]] + \_LookupJoin[LEFT,[language_code{r}#2],[language_code{f}#3],false,null] + |_Eval[[languages{f}#4 AS language_code#2, null[NULL] AS does_not_exist#5]] + | \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#8, first_name{f}#9, gender{f}#10, height{f}#11, height.float{f}#12, height.half_float{f}#13, height.scaled_float{f}#14, hire_date{f}#15, is_rehired{f}#16, job_positions{f}#17, languages{f}#4, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#3, language_name{f}#28] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/query.esql new file mode 100644 index 0000000000000..ba5f12db31aa2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL language_code = languages +| LOOKUP JOIN languages_lookup ON language_code +| EVAL x = does_not_exist::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected new file mode 100644 index 0000000000000..0e429b6f7e085 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected @@ -0,0 +1,6 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist{f}#0) > 0[INTEGER]] + \_LookupJoin[LEFT,[language_code{r}#1],[language_code{f}#2],false,null] + |_Eval[[languages{f}#3 AS language_code#1]] + | \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#3, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#0] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#2, language_name{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql new file mode 100644 index 0000000000000..face9633033a7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees +| EVAL language_code = languages +| LOOKUP JOIN languages_lookup ON language_code +| WHERE does_not_exist::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/analysis.expected new file mode 100644 index 0000000000000..204ffb0063c39 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/analysis.expected @@ -0,0 +1,7 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist{r}#0) > 0[INTEGER]] + \_LookupJoin[LEFT,[language_code{r}#1],[language_code{f}#2],false,null] + |_Eval[[languages{f}#3 AS language_code#1, null[NULL] AS does_not_exist#4]] + | \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#7, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#3, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#2, language_name{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/query.esql new file mode 100644 index 0000000000000..891443074f97b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL language_code = languages +| LOOKUP JOIN languages_lookup ON language_code +| WHERE does_not_exist::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/analysis.expected new file mode 100644 index 0000000000000..190b386040c51 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/analysis.expected @@ -0,0 +1,11 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, language_code{r}#1]] + \_UnionAll[[avg_worked_seconds{r}#2, birth_date{r}#3, emp_no{r}#0, first_name{r}#4, gender{r}#5, height{r}#6, height.float{r}#7, height.half_float{r}#8, height.scaled_float{r}#9, hire_date{r}#10, is_rehired{r}#11, job_positions{r}#12, languages{r}#13, languages.byte{r}#14, languages.long{r}#15, languages.short{r}#16, last_name{r}#17, salary{r}#18, salary_change{r}#19, salary_change.int{r}#20, salary_change.keyword{r}#21, salary_change.long{r}#22, still_hired{r}#23, language_code{r}#1, language_name{r}#24, does_not_exist{r}#25]] + |_Project[[avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48, language_code{r}#49, language_name{r}#50, does_not_exist{r}#51]] + | \_Eval[[null[INTEGER] AS language_code#49, null[KEYWORD] AS language_name#50, null[KEYWORD] AS does_not_exist#51]] + | \_EsRelation[employees][avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48] + \_Project[[avg_worked_seconds{r}#52, birth_date{r}#53, emp_no{r}#54, first_name{r}#55, gender{r}#56, height{r}#57, height.float{r}#58, height.half_float{r}#59, height.scaled_float{r}#60, hire_date{r}#61, is_rehired{r}#62, job_positions{r}#63, languages{r}#64, languages.byte{r}#65, languages.long{r}#66, languages.short{r}#67, last_name{r}#68, salary{r}#69, salary_change{r}#70, salary_change.int{r}#71, salary_change.keyword{r}#72, salary_change.long{r}#73, still_hired{r}#74, language_code{f}#75, language_name{f}#76, does_not_exist{f}#77]] + \_Eval[[null[LONG] AS avg_worked_seconds#52, null[DATETIME] AS birth_date#53, null[INTEGER] AS emp_no#54, null[KEYWORD] AS first_name#55, null[KEYWORD] AS gender#56, null[DOUBLE] AS height#57, null[DOUBLE] AS height.float#58, null[DOUBLE] AS height.half_float#59, null[DOUBLE] AS height.scaled_float#60, null[DATETIME] AS hire_date#61, null[BOOLEAN] AS is_rehired#62, null[KEYWORD] AS job_positions#63, null[INTEGER] AS languages#64, null[INTEGER] AS languages.byte#65, null[LONG] AS languages.long#66, null[INTEGER] AS languages.short#67, null[KEYWORD] AS last_name#68, null[INTEGER] AS salary#69, null[DOUBLE] AS salary_change#70, null[INTEGER] AS salary_change.int#71, null[KEYWORD] AS salary_change.keyword#72, null[LONG] AS salary_change.long#73, null[BOOLEAN] AS still_hired#74]] + \_Subquery[] + \_Filter[TOLONG(does_not_exist{f}#77) > 0[INTEGER]] + \_EsRelation[languages][language_code{f}#75, language_name{f}#76, does_not_exist{f}#77] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/query.esql new file mode 100644 index 0000000000000..f6110cf298e18 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees, (FROM languages | WHERE does_not_exist::LONG > 0) +| KEEP emp_no, language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/analysis.expected new file mode 100644 index 0000000000000..755aed8c8303b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/analysis.expected @@ -0,0 +1,12 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, language_code{r}#1]] + \_UnionAll[[avg_worked_seconds{r}#2, birth_date{r}#3, emp_no{r}#0, first_name{r}#4, gender{r}#5, height{r}#6, height.float{r}#7, height.half_float{r}#8, height.scaled_float{r}#9, hire_date{r}#10, is_rehired{r}#11, job_positions{r}#12, languages{r}#13, languages.byte{r}#14, languages.long{r}#15, languages.short{r}#16, last_name{r}#17, salary{r}#18, salary_change{r}#19, salary_change.int{r}#20, salary_change.keyword{r}#21, salary_change.long{r}#22, still_hired{r}#23, language_code{r}#1, language_name{r}#24, does_not_exist{r}#25]] + |_Project[[avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48, language_code{r}#49, language_name{r}#50, does_not_exist{r}#51]] + | \_Eval[[null[INTEGER] AS language_code#49, null[KEYWORD] AS language_name#50, null[NULL] AS does_not_exist#51]] + | \_EsRelation[employees][avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48] + \_Project[[avg_worked_seconds{r}#52, birth_date{r}#53, emp_no{r}#54, first_name{r}#55, gender{r}#56, height{r}#57, height.float{r}#58, height.half_float{r}#59, height.scaled_float{r}#60, hire_date{r}#61, is_rehired{r}#62, job_positions{r}#63, languages{r}#64, languages.byte{r}#65, languages.long{r}#66, languages.short{r}#67, last_name{r}#68, salary{r}#69, salary_change{r}#70, salary_change.int{r}#71, salary_change.keyword{r}#72, salary_change.long{r}#73, still_hired{r}#74, language_code{f}#75, language_name{f}#76, does_not_exist{r}#77]] + \_Eval[[null[LONG] AS avg_worked_seconds#52, null[DATETIME] AS birth_date#53, null[INTEGER] AS emp_no#54, null[KEYWORD] AS first_name#55, null[KEYWORD] AS gender#56, null[DOUBLE] AS height#57, null[DOUBLE] AS height.float#58, null[DOUBLE] AS height.half_float#59, null[DOUBLE] AS height.scaled_float#60, null[DATETIME] AS hire_date#61, null[BOOLEAN] AS is_rehired#62, null[KEYWORD] AS job_positions#63, null[INTEGER] AS languages#64, null[INTEGER] AS languages.byte#65, null[LONG] AS languages.long#66, null[INTEGER] AS languages.short#67, null[KEYWORD] AS last_name#68, null[INTEGER] AS salary#69, null[DOUBLE] AS salary_change#70, null[INTEGER] AS salary_change.int#71, null[KEYWORD] AS salary_change.keyword#72, null[LONG] AS salary_change.long#73, null[BOOLEAN] AS still_hired#74]] + \_Subquery[] + \_Filter[TOLONG(does_not_exist{r}#77) > 0[INTEGER]] + \_Eval[[null[NULL] AS does_not_exist#77]] + \_EsRelation[languages][language_code{f}#75, language_name{f}#76] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/query.esql new file mode 100644 index 0000000000000..6bd3350834a49 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees, (FROM languages | WHERE does_not_exist::LONG > 0) +| KEEP emp_no, language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..d6b8d29c43430 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected @@ -0,0 +1,11 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] + \_UnionAll[[avg_worked_seconds{r}#4, birth_date{r}#5, emp_no{r}#0, first_name{r}#6, gender{r}#7, height{r}#8, height.float{r}#9, height.half_float{r}#10, height.scaled_float{r}#11, hire_date{r}#12, is_rehired{r}#13, job_positions{r}#14, languages{r}#15, languages.byte{r}#16, languages.long{r}#17, languages.short{r}#18, last_name{r}#19, salary{r}#20, salary_change{r}#21, salary_change.int{r}#22, salary_change.keyword{r}#23, salary_change.long{r}#24, still_hired{r}#25, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] + |_Project[[avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48, language_code{r}#49, unmapped1{r}#50, unmapped2{r}#51]] + | \_Eval[[null[INTEGER] AS language_code#49, null[KEYWORD] AS unmapped1#50, null[KEYWORD] AS unmapped2#51]] + | \_EsRelation[employees][avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48] + \_Project[[avg_worked_seconds{r}#52, birth_date{r}#53, emp_no{r}#54, first_name{r}#55, gender{r}#56, height{r}#57, height.float{r}#58, height.half_float{r}#59, height.scaled_float{r}#60, hire_date{r}#61, is_rehired{r}#62, job_positions{r}#63, languages{r}#64, languages.byte{r}#65, languages.long{r}#66, languages.short{r}#67, last_name{r}#68, salary{r}#69, salary_change{r}#70, salary_change.int{r}#71, salary_change.keyword{r}#72, salary_change.long{r}#73, still_hired{r}#74, language_code{f}#75, unmapped1{f}#76, unmapped2{f}#77]] + \_Eval[[null[LONG] AS avg_worked_seconds#52, null[DATETIME] AS birth_date#53, null[INTEGER] AS emp_no#54, null[KEYWORD] AS first_name#55, null[KEYWORD] AS gender#56, null[DOUBLE] AS height#57, null[DOUBLE] AS height.float#58, null[DOUBLE] AS height.half_float#59, null[DOUBLE] AS height.scaled_float#60, null[DATETIME] AS hire_date#61, null[BOOLEAN] AS is_rehired#62, null[KEYWORD] AS job_positions#63, null[INTEGER] AS languages#64, null[INTEGER] AS languages.byte#65, null[LONG] AS languages.long#66, null[INTEGER] AS languages.short#67, null[KEYWORD] AS last_name#68, null[INTEGER] AS salary#69, null[DOUBLE] AS salary_change#70, null[INTEGER] AS salary_change.int#71, null[KEYWORD] AS salary_change.keyword#72, null[LONG] AS salary_change.long#73, null[BOOLEAN] AS still_hired#74]] + \_Subquery[] + \_Project[[language_code{f}#75, unmapped1{f}#76, unmapped2{f}#77]] + \_EsRelation[languages][language_code{f}#75, language_name{f}#78, unmapped1{f}#76, unmapped2{f}#77] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql new file mode 100644 index 0000000000000..f48daedc4ab1d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees, + (FROM languages | KEEP language_code, unmapped1, unmapped2) +| KEEP emp_no, language_code, unmapped1, unmapped2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..5edcc387fc727 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/analysis.expected @@ -0,0 +1,12 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] + \_UnionAll[[avg_worked_seconds{r}#4, birth_date{r}#5, emp_no{r}#0, first_name{r}#6, gender{r}#7, height{r}#8, height.float{r}#9, height.half_float{r}#10, height.scaled_float{r}#11, hire_date{r}#12, is_rehired{r}#13, job_positions{r}#14, languages{r}#15, languages.byte{r}#16, languages.long{r}#17, languages.short{r}#18, last_name{r}#19, salary{r}#20, salary_change{r}#21, salary_change.int{r}#22, salary_change.keyword{r}#23, salary_change.long{r}#24, still_hired{r}#25, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] + |_Project[[avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48, language_code{r}#49, unmapped1{r}#50, unmapped2{r}#51]] + | \_Eval[[null[INTEGER] AS language_code#49, null[NULL] AS unmapped1#50, null[NULL] AS unmapped2#51]] + | \_EsRelation[employees][avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48] + \_Project[[avg_worked_seconds{r}#52, birth_date{r}#53, emp_no{r}#54, first_name{r}#55, gender{r}#56, height{r}#57, height.float{r}#58, height.half_float{r}#59, height.scaled_float{r}#60, hire_date{r}#61, is_rehired{r}#62, job_positions{r}#63, languages{r}#64, languages.byte{r}#65, languages.long{r}#66, languages.short{r}#67, last_name{r}#68, salary{r}#69, salary_change{r}#70, salary_change.int{r}#71, salary_change.keyword{r}#72, salary_change.long{r}#73, still_hired{r}#74, language_code{f}#75, unmapped1{r}#76, unmapped2{r}#77]] + \_Eval[[null[LONG] AS avg_worked_seconds#52, null[DATETIME] AS birth_date#53, null[INTEGER] AS emp_no#54, null[KEYWORD] AS first_name#55, null[KEYWORD] AS gender#56, null[DOUBLE] AS height#57, null[DOUBLE] AS height.float#58, null[DOUBLE] AS height.half_float#59, null[DOUBLE] AS height.scaled_float#60, null[DATETIME] AS hire_date#61, null[BOOLEAN] AS is_rehired#62, null[KEYWORD] AS job_positions#63, null[INTEGER] AS languages#64, null[INTEGER] AS languages.byte#65, null[LONG] AS languages.long#66, null[INTEGER] AS languages.short#67, null[KEYWORD] AS last_name#68, null[INTEGER] AS salary#69, null[DOUBLE] AS salary_change#70, null[INTEGER] AS salary_change.int#71, null[KEYWORD] AS salary_change.keyword#72, null[LONG] AS salary_change.long#73, null[BOOLEAN] AS still_hired#74]] + \_Subquery[] + \_Project[[language_code{f}#75, unmapped1{r}#76, unmapped2{r}#77]] + \_Eval[[null[NULL] AS unmapped1#76, null[NULL] AS unmapped2#77]] + \_EsRelation[languages][language_code{f}#75, language_name{f}#78] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..eed7eb85db071 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees, + (FROM languages | KEEP language_code, unmapped1, unmapped2) +| KEEP emp_no, language_code, unmapped1, unmapped2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..0f0fb589b8c87 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected @@ -0,0 +1,11 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, language_code{r}#1, does_not_exist{r}#2]] + \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, language_code{r}#1, does_not_exist{r}#2]] + |_Project[[avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, language_code{r}#48, does_not_exist{r}#49]] + | \_Eval[[null[INTEGER] AS language_code#48, null[KEYWORD] AS does_not_exist#49]] + | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f}#73, does_not_exist{f}#74]] + \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] + \_Subquery[] + \_Project[[language_code{f}#73, does_not_exist{f}#74]] + \_EsRelation[languages][language_code{f}#73, language_name{f}#75, does_not_exist{f}#74] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql new file mode 100644 index 0000000000000..de7a454b426f7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees, (FROM languages | KEEP language_code, does_not_exist) +| KEEP emp_no, language_code, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..37e20fe2c90c4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected @@ -0,0 +1,12 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, language_code{r}#1, does_not_exist{r}#2]] + \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, language_code{r}#1, does_not_exist{r}#2]] + |_Project[[avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, language_code{r}#48, does_not_exist{r}#49]] + | \_Eval[[null[INTEGER] AS language_code#48, null[NULL] AS does_not_exist#49]] + | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f}#73, does_not_exist{r}#74]] + \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] + \_Subquery[] + \_Project[[language_code{f}#73, does_not_exist{r}#74]] + \_Eval[[null[NULL] AS does_not_exist#74]] + \_EsRelation[languages][language_code{f}#73, language_name{f}#75] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..8aa4d0fd116ce --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees, (FROM languages | KEEP language_code, does_not_exist) +| KEEP emp_no, language_code, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/analysis.expected new file mode 100644 index 0000000000000..c66e2c8319dba --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/analysis.expected @@ -0,0 +1,21 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, language_code{r}#1]] + \_Filter[$$does_not_exist$converted_to$long{r$}#2 > 0[INTEGER]] + \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, language_code{r}#1, language_name{r}#25, does_not_exist{r}#26, $$does_not_exist$converted_to$long{r$}#2]] + |_Project[[avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, language_code{r}#50, language_name{r}#51, does_not_exist{f}#52, $$does_not_exist$converted_to$long{r$}#53]] + | \_Eval[[TOLONG(does_not_exist{f}#52) AS $$does_not_exist$converted_to$long#53]] + | \_Eval[[null[INTEGER] AS language_code#50, null[KEYWORD] AS language_name#51]] + | \_EsRelation[employees][avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, does_not_exist{f}#52] + |_Project[[avg_worked_seconds{r}#54, birth_date{r}#55, emp_no{r}#56, first_name{r}#57, gender{r}#58, height{r}#59, height.float{r}#60, height.half_float{r}#61, height.scaled_float{r}#62, hire_date{r}#63, is_rehired{r}#64, job_positions{r}#65, languages{r}#66, languages.byte{r}#67, languages.long{r}#68, languages.short{r}#69, last_name{r}#70, salary{r}#71, salary_change{r}#72, salary_change.int{r}#73, salary_change.keyword{r}#74, salary_change.long{r}#75, still_hired{r}#76, language_code{f}#77, language_name{f}#78, does_not_exist{f}#79, $$does_not_exist$converted_to$long{r$}#80]] + | \_Eval[[TOLONG(does_not_exist{f}#79) AS $$does_not_exist$converted_to$long#80]] + | \_Eval[[null[LONG] AS avg_worked_seconds#54, null[DATETIME] AS birth_date#55, null[INTEGER] AS emp_no#56, null[KEYWORD] AS first_name#57, null[KEYWORD] AS gender#58, null[DOUBLE] AS height#59, null[DOUBLE] AS height.float#60, null[DOUBLE] AS height.half_float#61, null[DOUBLE] AS height.scaled_float#62, null[DATETIME] AS hire_date#63, null[BOOLEAN] AS is_rehired#64, null[KEYWORD] AS job_positions#65, null[INTEGER] AS languages#66, null[INTEGER] AS languages.byte#67, null[LONG] AS languages.long#68, null[INTEGER] AS languages.short#69, null[KEYWORD] AS last_name#70, null[INTEGER] AS salary#71, null[DOUBLE] AS salary_change#72, null[INTEGER] AS salary_change.int#73, null[KEYWORD] AS salary_change.keyword#74, null[LONG] AS salary_change.long#75, null[BOOLEAN] AS still_hired#76]] + | \_Subquery[] + | \_Filter[language_code{f}#77 > 0[INTEGER]] + | \_EsRelation[languages][language_code{f}#77, language_name{f}#78, does_not_exist{f}#79] + \_Project[[avg_worked_seconds{f}#81, birth_date{f}#82, emp_no{f}#83, first_name{f}#84, gender{f}#85, height{f}#86, height.float{f}#87, height.half_float{f}#88, height.scaled_float{f}#89, hire_date{f}#90, is_rehired{f}#91, job_positions{f}#92, languages{f}#93, languages.byte{f}#94, languages.long{f}#95, languages.short{f}#96, last_name{f}#97, salary{f}#98, salary_change{f}#99, salary_change.int{f}#100, salary_change.keyword{f}#101, salary_change.long{f}#102, still_hired{f}#103, language_code{r}#104, language_name{f}#105, does_not_exist{f}#106, $$does_not_exist$converted_to$long{r$}#107]] + \_Eval[[TOLONG(does_not_exist{f}#106) AS $$does_not_exist$converted_to$long#107]] + \_Subquery[] + \_LookupJoin[LEFT,[language_code{r}#104],[language_code{f}#108],false,null] + |_Eval[[languages{f}#93 AS language_code#104]] + | \_EsRelation[employees][avg_worked_seconds{f}#81, birth_date{f}#82, emp_no{f}#83, first_name{f}#84, gender{f}#85, height{f}#86, height.float{f}#87, height.half_float{f}#88, height.scaled_float{f}#89, hire_date{f}#90, is_rehired{f}#91, job_positions{f}#92, languages{f}#93, languages.byte{f}#94, languages.long{f}#95, languages.short{f}#96, last_name{f}#97, salary{f}#98, salary_change{f}#99, salary_change.int{f}#100, salary_change.keyword{f}#101, salary_change.long{f}#102, still_hired{f}#103, does_not_exist{f}#106] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#108, language_name{f}#105] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/query.esql new file mode 100644 index 0000000000000..9e1ecb142ea61 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/query.esql @@ -0,0 +1,5 @@ +SET unmapped_fields="load"; FROM employees, + (FROM languages | WHERE language_code > 0), + (FROM employees | EVAL language_code = languages | LOOKUP JOIN languages_lookup ON language_code) +| WHERE does_not_exist::LONG > 0 +| KEEP emp_no, language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/analysis.expected new file mode 100644 index 0000000000000..88494026b12bd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/analysis.expected @@ -0,0 +1,23 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, language_code{r}#1]] + \_Filter[$$does_not_exist$converted_to$long{r$}#2 > 0[INTEGER]] + \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, language_code{r}#1, language_name{r}#25, does_not_exist{r}#26, $$does_not_exist$converted_to$long{r$}#2]] + |_Project[[avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, language_code{r}#50, language_name{r}#51, does_not_exist{r}#52, $$does_not_exist$converted_to$long{r$}#53]] + | \_Eval[[TOLONG(does_not_exist{r}#52) AS $$does_not_exist$converted_to$long#53]] + | \_Eval[[null[INTEGER] AS language_code#50, null[KEYWORD] AS language_name#51, null[NULL] AS does_not_exist#52]] + | \_EsRelation[employees][avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49] + |_Project[[avg_worked_seconds{r}#54, birth_date{r}#55, emp_no{r}#56, first_name{r}#57, gender{r}#58, height{r}#59, height.float{r}#60, height.half_float{r}#61, height.scaled_float{r}#62, hire_date{r}#63, is_rehired{r}#64, job_positions{r}#65, languages{r}#66, languages.byte{r}#67, languages.long{r}#68, languages.short{r}#69, last_name{r}#70, salary{r}#71, salary_change{r}#72, salary_change.int{r}#73, salary_change.keyword{r}#74, salary_change.long{r}#75, still_hired{r}#76, language_code{f}#77, language_name{f}#78, does_not_exist{r}#79, $$does_not_exist$converted_to$long{r$}#80]] + | \_Eval[[TOLONG(does_not_exist{r}#79) AS $$does_not_exist$converted_to$long#80]] + | \_Eval[[null[LONG] AS avg_worked_seconds#54, null[DATETIME] AS birth_date#55, null[INTEGER] AS emp_no#56, null[KEYWORD] AS first_name#57, null[KEYWORD] AS gender#58, null[DOUBLE] AS height#59, null[DOUBLE] AS height.float#60, null[DOUBLE] AS height.half_float#61, null[DOUBLE] AS height.scaled_float#62, null[DATETIME] AS hire_date#63, null[BOOLEAN] AS is_rehired#64, null[KEYWORD] AS job_positions#65, null[INTEGER] AS languages#66, null[INTEGER] AS languages.byte#67, null[LONG] AS languages.long#68, null[INTEGER] AS languages.short#69, null[KEYWORD] AS last_name#70, null[INTEGER] AS salary#71, null[DOUBLE] AS salary_change#72, null[INTEGER] AS salary_change.int#73, null[KEYWORD] AS salary_change.keyword#74, null[LONG] AS salary_change.long#75, null[BOOLEAN] AS still_hired#76]] + | \_Subquery[] + | \_Filter[language_code{f}#77 > 0[INTEGER]] + | \_Eval[[null[NULL] AS does_not_exist#79]] + | \_EsRelation[languages][language_code{f}#77, language_name{f}#78] + \_Project[[avg_worked_seconds{f}#81, birth_date{f}#82, emp_no{f}#83, first_name{f}#84, gender{f}#85, height{f}#86, height.float{f}#87, height.half_float{f}#88, height.scaled_float{f}#89, hire_date{f}#90, is_rehired{f}#91, job_positions{f}#92, languages{f}#93, languages.byte{f}#94, languages.long{f}#95, languages.short{f}#96, last_name{f}#97, salary{f}#98, salary_change{f}#99, salary_change.int{f}#100, salary_change.keyword{f}#101, salary_change.long{f}#102, still_hired{f}#103, language_code{r}#104, language_name{f}#105, does_not_exist{r}#106, $$does_not_exist$converted_to$long{r$}#107]] + \_Eval[[TOLONG(does_not_exist{r}#106) AS $$does_not_exist$converted_to$long#107]] + \_Subquery[] + \_LookupJoin[LEFT,[language_code{r}#104],[language_code{f}#108],false,null] + |_Eval[[languages{f}#93 AS language_code#104, null[NULL] AS does_not_exist#109]] + | \_EsRelation[employees][avg_worked_seconds{f}#81, birth_date{f}#82, emp_no{f}#83, first_name{f}#84, gender{f}#85, height{f}#86, height.float{f}#87, height.half_float{f}#88, height.scaled_float{f}#89, hire_date{f}#90, is_rehired{f}#91, job_positions{f}#92, languages{f}#93, languages.byte{f}#94, languages.long{f}#95, languages.short{f}#96, last_name{f}#97, salary{f}#98, salary_change{f}#99, salary_change.int{f}#100, salary_change.keyword{f}#101, salary_change.long{f}#102, still_hired{f}#103] + \_Eval[[null[NULL] AS does_not_exist#106]] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#108, language_name{f}#105] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/query.esql new file mode 100644 index 0000000000000..1cae2badc15ab --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/query.esql @@ -0,0 +1,5 @@ +SET unmapped_fields="nullify"; FROM employees, + (FROM languages | WHERE language_code > 0), + (FROM employees | EVAL language_code = languages | LOOKUP JOIN languages_lookup ON language_code) +| WHERE does_not_exist::LONG > 0 +| KEEP emp_no, language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected new file mode 100644 index 0000000000000..48317bbb23980 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected @@ -0,0 +1,11 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, max_ts{r}#1, does_not_exist{r}#2]] + \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, max_ts{r}#1, does_not_exist{r}#2]] + |_Project[[avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, max_ts{r}#48, does_not_exist{r}#49]] + | \_Eval[[null[DATETIME] AS max_ts#48, null[KEYWORD] AS does_not_exist#49]] + | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, max_ts{r}#73, does_not_exist{f}#74]] + \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] + \_Subquery[] + \_Aggregate[[does_not_exist{f}#74],[MAX(@timestamp{f}#75,true[BOOLEAN],PT0S[TIME_DURATION]) AS max_ts#73, does_not_exist{f}#74]] + \_EsRelation[sample_data][@timestamp{f}#75, client_ip{f}#76, event_duration{f}#77, message{f}#78, does_not_exist{f}#74] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql new file mode 100644 index 0000000000000..dabf6fc1b0e8c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees, (FROM sample_data | STATS max_ts = MAX(@timestamp) BY does_not_exist) +| KEEP emp_no, max_ts, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/analysis.expected new file mode 100644 index 0000000000000..1def35de13537 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/analysis.expected @@ -0,0 +1,12 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, max_ts{r}#1, does_not_exist{r}#2]] + \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, max_ts{r}#1, does_not_exist{r}#2]] + |_Project[[avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, max_ts{r}#48, does_not_exist{r}#49]] + | \_Eval[[null[DATETIME] AS max_ts#48, null[NULL] AS does_not_exist#49]] + | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, max_ts{r}#73, does_not_exist{r}#74]] + \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] + \_Subquery[] + \_Aggregate[[does_not_exist{r}#74],[MAX(@timestamp{f}#75,true[BOOLEAN],PT0S[TIME_DURATION]) AS max_ts#73, does_not_exist{r}#74]] + \_Eval[[null[NULL] AS does_not_exist#74]] + \_EsRelation[sample_data][@timestamp{f}#75, client_ip{f}#76, event_duration{f}#77, message{f}#78] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/query.esql new file mode 100644 index 0000000000000..7c5a4d44bddb0 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees, (FROM sample_data | STATS max_ts = MAX(@timestamp) BY does_not_exist) +| KEEP emp_no, max_ts, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/analysis.expected new file mode 100644 index 0000000000000..0eadb71bf5ba0 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#0) AS tbucket(1 hour)#1],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#2, tbucket(1 hour){r}#1]] + \_Filter[TOLONG(does_not_exist{f}#3) > 0[INTEGER]] + \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6, does_not_exist{f}#3] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/query.esql new file mode 100644 index 0000000000000..b32e8bd6d23f4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM sample_data +| WHERE does_not_exist::LONG > 0 +| STATS c = COUNT(*) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/analysis.expected new file mode 100644 index 0000000000000..91da106ed92ba --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#0) AS tbucket(1 hour)#1],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#2, tbucket(1 hour){r}#1]] + \_Filter[TOLONG(does_not_exist{r}#3) > 0[INTEGER]] + \_Eval[[null[NULL] AS does_not_exist#3]] + \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/query.esql new file mode 100644 index 0000000000000..b6b417785892b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM sample_data +| WHERE does_not_exist::LONG > 0 +| STATS c = COUNT(*) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..5dc208a9d01de --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TBUCKET(P1D[DATE_PERIOD],@timestamp{f}#0) AS tbucket(1 day)#1],[SUM(TODOUBLE(does_not_exist{f}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, tbucket(1 day){r}#1]] + \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#5, event_duration{f}#6, message{f}#7, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/query.esql new file mode 100644 index 0000000000000..8ee634876a9b7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data +| STATS s = SUM(does_not_exist::DOUBLE), c = COUNT(*) BY tbucket(1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..630cfad99e1d9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TBUCKET(P1D[DATE_PERIOD],@timestamp{f}#0) AS tbucket(1 day)#1],[SUM(TODOUBLE(does_not_exist{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, tbucket(1 day){r}#1]] + \_Eval[[null[NULL] AS does_not_exist#2]] + \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#5, event_duration{f}#6, message{f}#7] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..cbf52dd9c02eb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data +| STATS s = SUM(does_not_exist::DOUBLE), c = COUNT(*) BY tbucket(1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..0a5930587890d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#0) AS tbucket(1 hour)#1, does_not_exist{f}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#3, tbucket(1 hour){r}#1, does_not_exist{f}#2]] + \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/query.esql new file mode 100644 index 0000000000000..33c3866fe3563 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data +| STATS c = COUNT(*) BY tbucket(1 hour), does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..0ddcf7afa969d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#0) AS tbucket(1 hour)#1, does_not_exist{r}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#3, tbucket(1 hour){r}#1, does_not_exist{r}#2]] + \_Eval[[null[NULL] AS does_not_exist#2]] + \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..0ddc50c5758d4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data +| STATS c = COUNT(*) BY tbucket(1 hour), does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/analysis.expected new file mode 100644 index 0000000000000..b94f828d0e124 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TBUCKET(P1D[DATE_PERIOD],@timestamp{f}#0) AS tbucket(1 day)#1],[SUM(TODOUBLE(does_not_exist{f}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, tbucket(1 day){r}#1]] + \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/query.esql new file mode 100644 index 0000000000000..f0d33fb33d8a2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data +| STATS s = SUM(does_not_exist::DOUBLE) BY tbucket(1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/analysis.expected new file mode 100644 index 0000000000000..b9d36a0af9fef --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TBUCKET(P1D[DATE_PERIOD],@timestamp{f}#0) AS tbucket(1 day)#1],[SUM(TODOUBLE(does_not_exist{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, tbucket(1 day){r}#1]] + \_Eval[[null[NULL] AS does_not_exist#2]] + \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/query.esql new file mode 100644 index 0000000000000..dbe8b20220655 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data +| STATS s = SUM(does_not_exist::DOUBLE) BY tbucket(1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/analysis.expected new file mode 100644 index 0000000000000..461abb31b2a3e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000000[INTEGER],false,false] +\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(AVGOVERTIME(network.eth0.rx{f}#3,true[BOOLEAN],PT0S[TIME_DURATION]),true[BOOLEAN],PT0S[TIME_DURATION]) AS a#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] + \_Filter[TOLONG(does_not_exist{f}#5) > 0[INTEGER]] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#6, cluster{f}#7, event{f}#8, event_city{f}#9, event_city_boundary{f}#10, event_location{f}#11, event_log{f}#12, event_shape{f}#13, events_received{f}#14, network.bytes_in{f}#15, network.cost{f}#16, network.eth0.currently_connected_clients{f}#17, network.eth0.firmware_version{f}#18, network.eth0.last_up{f}#19, network.eth0.rx{f}#3, network.eth0.tx{f}#20, network.eth0.up{f}#21, network.total_bytes_in{f}#22, network.total_bytes_out{f}#23, network.total_cost{f}#24, pod{f}#25, region{f}#26, _timeseries{f}#0, does_not_exist{f}#5] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/query.esql new file mode 100644 index 0000000000000..07b29b5b8cfac --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; TS k8s +| WHERE does_not_exist::LONG > 0 +| STATS a = AVG_OVER_TIME(network.eth0.rx) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/analysis.expected new file mode 100644 index 0000000000000..d9cd26163304f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000000[INTEGER],false,false] +\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(AVGOVERTIME(network.eth0.rx{f}#3,true[BOOLEAN],PT0S[TIME_DURATION]),true[BOOLEAN],PT0S[TIME_DURATION]) AS a#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] + \_Filter[TOLONG(does_not_exist{r}#5) > 0[INTEGER]] + \_Eval[[null[NULL] AS does_not_exist#5]] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#6, cluster{f}#7, event{f}#8, event_city{f}#9, event_city_boundary{f}#10, event_location{f}#11, event_log{f}#12, event_shape{f}#13, events_received{f}#14, network.bytes_in{f}#15, network.cost{f}#16, network.eth0.currently_connected_clients{f}#17, network.eth0.firmware_version{f}#18, network.eth0.last_up{f}#19, network.eth0.rx{f}#3, network.eth0.tx{f}#20, network.eth0.up{f}#21, network.total_bytes_in{f}#22, network.total_bytes_out{f}#23, network.total_cost{f}#24, pod{f}#25, region{f}#26, _timeseries{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/query.esql new file mode 100644 index 0000000000000..3ae9a1aa9dbe9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; TS k8s +| WHERE does_not_exist::LONG > 0 +| STATS a = AVG_OVER_TIME(network.eth0.rx) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..e19e2e842bf54 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[@timestamp{f}#0, cluster{f}#1, x{r}#2]] + \_Eval[[TODOUBLE(does_not_exist{f}#3) + network.cost{f}#4 AS x#2]] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#0, client.ip{f}#5, cluster{f}#1, event{f}#6, event_city{f}#7, event_city_boundary{f}#8, event_location{f}#9, event_log{f}#10, event_shape{f}#11, events_received{f}#12, network.bytes_in{f}#13, network.cost{f}#4, network.eth0.currently_connected_clients{f}#14, network.eth0.firmware_version{f}#15, network.eth0.last_up{f}#16, network.eth0.rx{f}#17, network.eth0.tx{f}#18, network.eth0.up{f}#19, network.total_bytes_in{f}#20, network.total_bytes_out{f}#21, network.total_cost{f}#22, pod{f}#23, region{f}#24, does_not_exist{f}#3] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/query.esql new file mode 100644 index 0000000000000..94e371a53661c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; TS k8s +| EVAL x = does_not_exist::DOUBLE + network.cost +| KEEP @timestamp, cluster, x diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..0b49d801279f5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Project[[@timestamp{f}#0, cluster{f}#1, x{r}#2]] + \_Eval[[TODOUBLE(does_not_exist{r}#3) + network.cost{f}#4 AS x#2]] + \_Eval[[null[NULL] AS does_not_exist#3]] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#0, client.ip{f}#5, cluster{f}#1, event{f}#6, event_city{f}#7, event_city_boundary{f}#8, event_location{f}#9, event_log{f}#10, event_shape{f}#11, events_received{f}#12, network.bytes_in{f}#13, network.cost{f}#4, network.eth0.currently_connected_clients{f}#14, network.eth0.firmware_version{f}#15, network.eth0.last_up{f}#16, network.eth0.rx{f}#17, network.eth0.tx{f}#18, network.eth0.up{f}#19, network.total_bytes_in{f}#20, network.total_bytes_out{f}#21, network.total_cost{f}#22, pod{f}#23, region{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..a9a6f91b2b94b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; TS k8s +| EVAL x = does_not_exist::DOUBLE + network.cost +| KEEP @timestamp, cluster, x diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..a53ba9b57e55d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000000[INTEGER],false,false] +\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(FIRSTOVERTIME(TODOUBLE(does_not_exist{f}#3),true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS f#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#5, cluster{f}#6, event{f}#7, event_city{f}#8, event_city_boundary{f}#9, event_location{f}#10, event_log{f}#11, event_shape{f}#12, events_received{f}#13, network.bytes_in{f}#14, network.cost{f}#15, network.eth0.currently_connected_clients{f}#16, network.eth0.firmware_version{f}#17, network.eth0.last_up{f}#18, network.eth0.rx{f}#19, network.eth0.tx{f}#20, network.eth0.up{f}#21, network.total_bytes_in{f}#22, network.total_bytes_out{f}#23, network.total_cost{f}#24, pod{f}#25, region{f}#26, _timeseries{f}#0, does_not_exist{f}#3] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/query.esql new file mode 100644 index 0000000000000..8cddd18499f03 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; TS k8s +| STATS f = FIRST_OVER_TIME(does_not_exist::DOUBLE) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..f5b122a261793 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000000[INTEGER],false,false] +\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(FIRSTOVERTIME(TODOUBLE(does_not_exist{r}#3),true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS f#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] + \_Eval[[null[NULL] AS does_not_exist#3]] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#5, cluster{f}#6, event{f}#7, event_city{f}#8, event_city_boundary{f}#9, event_location{f}#10, event_log{f}#11, event_shape{f}#12, events_received{f}#13, network.bytes_in{f}#14, network.cost{f}#15, network.eth0.currently_connected_clients{f}#16, network.eth0.firmware_version{f}#17, network.eth0.last_up{f}#18, network.eth0.rx{f}#19, network.eth0.tx{f}#20, network.eth0.up{f}#21, network.total_bytes_in{f}#22, network.total_bytes_out{f}#23, network.total_cost{f}#24, pod{f}#25, region{f}#26, _timeseries{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..830583a7048ff --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; TS k8s +| STATS f = FIRST_OVER_TIME(does_not_exist::DOUBLE) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..4819c89f1c210 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[@timestamp{f}#0, cluster{f}#1, does_not_exist{f}#2]] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#0, client.ip{f}#3, cluster{f}#1, event{f}#4, event_city{f}#5, event_city_boundary{f}#6, event_location{f}#7, event_log{f}#8, event_shape{f}#9, events_received{f}#10, network.bytes_in{f}#11, network.cost{f}#12, network.eth0.currently_connected_clients{f}#13, network.eth0.firmware_version{f}#14, network.eth0.last_up{f}#15, network.eth0.rx{f}#16, network.eth0.tx{f}#17, network.eth0.up{f}#18, network.total_bytes_in{f}#19, network.total_bytes_out{f}#20, network.total_cost{f}#21, pod{f}#22, region{f}#23, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/query.esql new file mode 100644 index 0000000000000..d872e477d1225 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; TS k8s +| KEEP @timestamp, cluster, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..6a20c2f90cbfd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[@timestamp{f}#0, cluster{f}#1, does_not_exist{r}#2]] + \_Eval[[null[NULL] AS does_not_exist#2]] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#0, client.ip{f}#3, cluster{f}#1, event{f}#4, event_city{f}#5, event_city_boundary{f}#6, event_location{f}#7, event_log{f}#8, event_shape{f}#9, events_received{f}#10, network.bytes_in{f}#11, network.cost{f}#12, network.eth0.currently_connected_clients{f}#13, network.eth0.firmware_version{f}#14, network.eth0.last_up{f}#15, network.eth0.rx{f}#16, network.eth0.tx{f}#17, network.eth0.up{f}#18, network.total_bytes_in{f}#19, network.total_bytes_out{f}#20, network.total_cost{f}#21, pod{f}#22, region{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..c6b92a7280467 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; TS k8s +| KEEP @timestamp, cluster, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/analysis.expected new file mode 100644 index 0000000000000..57b3580871a30 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000000[INTEGER],false,false] +\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(MAXOVERTIME(network.eth0.tx{f}#3,true[BOOLEAN],PT0S[TIME_DURATION]),true[BOOLEAN],PT0S[TIME_DURATION]) AS m#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] + \_Eval[[TODOUBLE(does_not_exist{f}#5) + 1[INTEGER] AS x#6]] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#7, cluster{f}#8, event{f}#9, event_city{f}#10, event_city_boundary{f}#11, event_location{f}#12, event_log{f}#13, event_shape{f}#14, events_received{f}#15, network.bytes_in{f}#16, network.cost{f}#17, network.eth0.currently_connected_clients{f}#18, network.eth0.firmware_version{f}#19, network.eth0.last_up{f}#20, network.eth0.rx{f}#21, network.eth0.tx{f}#3, network.eth0.up{f}#22, network.total_bytes_in{f}#23, network.total_bytes_out{f}#24, network.total_cost{f}#25, pod{f}#26, region{f}#27, _timeseries{f}#0, does_not_exist{f}#5] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/query.esql new file mode 100644 index 0000000000000..5d1d571c052d2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; TS k8s +| EVAL x = does_not_exist::DOUBLE + 1 +| STATS m = MAX_OVER_TIME(network.eth0.tx) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/analysis.expected new file mode 100644 index 0000000000000..418f1280705a3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000000[INTEGER],false,false] +\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(MAXOVERTIME(network.eth0.tx{f}#3,true[BOOLEAN],PT0S[TIME_DURATION]),true[BOOLEAN],PT0S[TIME_DURATION]) AS m#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] + \_Eval[[TODOUBLE(does_not_exist{r}#5) + 1[INTEGER] AS x#6]] + \_Eval[[null[NULL] AS does_not_exist#5]] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#7, cluster{f}#8, event{f}#9, event_city{f}#10, event_city_boundary{f}#11, event_location{f}#12, event_log{f}#13, event_shape{f}#14, events_received{f}#15, network.bytes_in{f}#16, network.cost{f}#17, network.eth0.currently_connected_clients{f}#18, network.eth0.firmware_version{f}#19, network.eth0.last_up{f}#20, network.eth0.rx{f}#21, network.eth0.tx{f}#3, network.eth0.up{f}#22, network.total_bytes_in{f}#23, network.total_bytes_out{f}#24, network.total_cost{f}#25, pod{f}#26, region{f}#27, _timeseries{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/query.esql new file mode 100644 index 0000000000000..8cfedb3e58a5c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; TS k8s +| EVAL x = does_not_exist::DOUBLE + 1 +| STATS m = MAX_OVER_TIME(network.eth0.tx) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/analysis.expected new file mode 100644 index 0000000000000..c60ce59bffa66 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000000[INTEGER],false,false] +\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(RATE(network.total_cost{f}#3,true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS r#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] + \_Filter[TOLONG(does_not_exist{f}#5) > 0[INTEGER]] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#6, cluster{f}#7, event{f}#8, event_city{f}#9, event_city_boundary{f}#10, event_location{f}#11, event_log{f}#12, event_shape{f}#13, events_received{f}#14, network.bytes_in{f}#15, network.cost{f}#16, network.eth0.currently_connected_clients{f}#17, network.eth0.firmware_version{f}#18, network.eth0.last_up{f}#19, network.eth0.rx{f}#20, network.eth0.tx{f}#21, network.eth0.up{f}#22, network.total_bytes_in{f}#23, network.total_bytes_out{f}#24, network.total_cost{f}#3, pod{f}#25, region{f}#26, _timeseries{f}#0, does_not_exist{f}#5] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/query.esql new file mode 100644 index 0000000000000..26c827ff5d107 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; TS k8s +| WHERE does_not_exist::LONG > 0 +| STATS r = RATE(network.total_cost) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/analysis.expected new file mode 100644 index 0000000000000..e51c21b27f6a7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000000[INTEGER],false,false] +\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(RATE(network.total_cost{f}#3,true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS r#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] + \_Filter[TOLONG(does_not_exist{r}#5) > 0[INTEGER]] + \_Eval[[null[NULL] AS does_not_exist#5]] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#6, cluster{f}#7, event{f}#8, event_city{f}#9, event_city_boundary{f}#10, event_location{f}#11, event_log{f}#12, event_shape{f}#13, events_received{f}#14, network.bytes_in{f}#15, network.cost{f}#16, network.eth0.currently_connected_clients{f}#17, network.eth0.firmware_version{f}#18, network.eth0.last_up{f}#19, network.eth0.rx{f}#20, network.eth0.tx{f}#21, network.eth0.up{f}#22, network.total_bytes_in{f}#23, network.total_bytes_out{f}#24, network.total_cost{f}#3, pod{f}#25, region{f}#26, _timeseries{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/query.esql new file mode 100644 index 0000000000000..142d352cd603f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; TS k8s +| WHERE does_not_exist::LONG > 0 +| STATS r = RATE(network.total_cost) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..41c760dcac978 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000000[INTEGER],false,false] +\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(RATE(does_not_exist{r}#3,true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS r#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] + \_Eval[[null[NULL] AS does_not_exist#3]] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#5, cluster{f}#6, event{f}#7, event_city{f}#8, event_city_boundary{f}#9, event_location{f}#10, event_log{f}#11, event_shape{f}#12, events_received{f}#13, network.bytes_in{f}#14, network.cost{f}#15, network.eth0.currently_connected_clients{f}#16, network.eth0.firmware_version{f}#17, network.eth0.last_up{f}#18, network.eth0.rx{f}#19, network.eth0.tx{f}#20, network.eth0.up{f}#21, network.total_bytes_in{f}#22, network.total_bytes_out{f}#23, network.total_cost{f}#24, pod{f}#25, region{f}#26, _timeseries{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..f398daec38c45 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; TS k8s +| STATS r = RATE(does_not_exist) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateWithUnmappedGroupBy/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateWithUnmappedGroupBy/nullify/query.esql new file mode 100644 index 0000000000000..f084c1078693a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateWithUnmappedGroupBy/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; TS k8s +| STATS r = RATE(network.total_cost) BY tbucket(1 hour), does_not_exist From eefa9cf25980413163bb43d3cda035ea9ed970d1 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 3 Feb 2026 21:28:52 +0200 Subject: [PATCH 019/137] Add multi index tests --- .../analysis/AnalyzerUnmappedGoldenTests.java | 37 +++++++++++++++++++ .../load/analysis.expected | 3 ++ .../load/query.esql | 2 + .../nullify/analysis.expected | 3 ++ .../nullify/query.esql | 2 + .../load/analysis.expected | 4 ++ .../load/query.esql | 3 ++ .../nullify/analysis.expected | 4 ++ .../nullify/query.esql | 3 ++ .../load/analysis.expected | 3 ++ .../testPartiallyMappedField/load/query.esql | 2 + .../nullify/analysis.expected | 4 ++ .../nullify/query.esql | 2 + .../load/analysis.expected | 4 ++ .../load/query.esql | 3 ++ .../nullify/analysis.expected | 5 +++ .../nullify/query.esql | 3 ++ .../load/analysis.expected | 3 ++ .../load/query.esql | 2 + .../nullify/analysis.expected | 4 ++ .../nullify/query.esql | 2 + 21 files changed, 98 insertions(+) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/query.esql diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java index ce64011cdcb6c..1d480c6701019 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -363,6 +363,43 @@ public void testTimeSeriesFirstOverTimeUnmapped() throws Exception { """); } + public void testPartiallyMappedField() throws Exception { + runTests(""" + FROM sample_data, partial_mapping_sample_data + | KEEP @timestamp, message, unmapped_message + """); + } + + public void testPartiallyMappedFieldWithStats() throws Exception { + runTests(""" + FROM sample_data, partial_mapping_sample_data + | STATS c = COUNT(*) BY unmapped_message + """); + } + + public void testPartiallyMappedFieldWithEval() throws Exception { + runTests(""" + FROM sample_data, partial_mapping_sample_data + | EVAL x = COALESCE(unmapped_message, "missing") + | KEEP @timestamp, x + """); + } + + public void testDifferentTypesAcrossIndices() throws Exception { + runTests(""" + FROM sample_data, sample_data_ts_long + | KEEP @timestamp, message + """); + } + + public void testDifferentTypesWithCast() throws Exception { + runTests(""" + FROM sample_data, sample_data_ts_long + | EVAL ts = @timestamp::STRING + | KEEP ts, message + """); + } + @Override protected java.util.List filteredWarnings() { return withDefaultLimitWarning(super.filteredWarnings()); diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected new file mode 100644 index 0000000000000..60246e2a52c6f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[!@timestamp, message{f}#0]] + \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#1, event_duration{f}#2, message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/query.esql new file mode 100644 index 0000000000000..36f26bbad39a7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, sample_data_ts_long +| KEEP @timestamp, message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected new file mode 100644 index 0000000000000..60246e2a52c6f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[!@timestamp, message{f}#0]] + \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#1, event_duration{f}#2, message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/query.esql new file mode 100644 index 0000000000000..b469337a46ebc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, sample_data_ts_long +| KEEP @timestamp, message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected new file mode 100644 index 0000000000000..c13045a018215 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[ts{r}#0, message{f}#1]] + \_Eval[[$$@timestamp$converted_to$keyword{f$}#2 AS ts#0]] + \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#3, event_duration{f}#4, message{f}#1, $$@timestamp$converted_to$keyword{f$}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/query.esql new file mode 100644 index 0000000000000..c739306c06b40 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM sample_data, sample_data_ts_long +| EVAL ts = @timestamp::STRING +| KEEP ts, message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected new file mode 100644 index 0000000000000..c13045a018215 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[ts{r}#0, message{f}#1]] + \_Eval[[$$@timestamp$converted_to$keyword{f$}#2 AS ts#0]] + \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#3, event_duration{f}#4, message{f}#1, $$@timestamp$converted_to$keyword{f$}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql new file mode 100644 index 0000000000000..8a4145812c548 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM sample_data, sample_data_ts_long +| EVAL ts = @timestamp::STRING +| KEEP ts, message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/analysis.expected new file mode 100644 index 0000000000000..09d01f355c3bc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[@timestamp{f}#0, message{f}#1, unmapped_message{f}#2]] + \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#3, event_duration{f}#4, message{f}#1, unmapped_message{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/query.esql new file mode 100644 index 0000000000000..84d4cfd6038b2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, partial_mapping_sample_data +| KEEP @timestamp, message, unmapped_message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/analysis.expected new file mode 100644 index 0000000000000..c23e90cb6e10b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[@timestamp{f}#0, message{f}#1, unmapped_message{r}#2]] + \_Eval[[null[NULL] AS unmapped_message#2]] + \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#3, event_duration{f}#4, message{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/query.esql new file mode 100644 index 0000000000000..f685cd7d68cda --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, partial_mapping_sample_data +| KEEP @timestamp, message, unmapped_message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected new file mode 100644 index 0000000000000..c5c5603a87da1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[@timestamp{f}#0, x{r}#1]] + \_Eval[[COALESCE(unmapped_message{f}#2,missing[KEYWORD]) AS x#1]] + \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#3, event_duration{f}#4, message{f}#5, unmapped_message{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/query.esql new file mode 100644 index 0000000000000..3d56b92b85d47 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM sample_data, partial_mapping_sample_data +| EVAL x = COALESCE(unmapped_message, "missing") +| KEEP @timestamp, x diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected new file mode 100644 index 0000000000000..d41f33ebff73e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Project[[@timestamp{f}#0, x{r}#1]] + \_Eval[[COALESCE(unmapped_message{r}#2,missing[KEYWORD]) AS x#1]] + \_Eval[[null[NULL] AS unmapped_message#2]] + \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#3, event_duration{f}#4, message{f}#5] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/query.esql new file mode 100644 index 0000000000000..b066c80c57f4d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM sample_data, partial_mapping_sample_data +| EVAL x = COALESCE(unmapped_message, "missing") +| KEEP @timestamp, x diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/analysis.expected new file mode 100644 index 0000000000000..30aecb7154ced --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[unmapped_message{f}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#1, unmapped_message{f}#0]] + \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#5, unmapped_message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/query.esql new file mode 100644 index 0000000000000..870af673da1a0 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, partial_mapping_sample_data +| STATS c = COUNT(*) BY unmapped_message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/analysis.expected new file mode 100644 index 0000000000000..e1f96c50471b1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[unmapped_message{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#1, unmapped_message{r}#0]] + \_Eval[[null[NULL] AS unmapped_message#0]] + \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#5] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/query.esql new file mode 100644 index 0000000000000..d44b1ad301021 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, partial_mapping_sample_data +| STATS c = COUNT(*) BY unmapped_message From 7f692347ad4773add0167f8857d71ac45295973c Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 4 Feb 2026 13:35:11 +0200 Subject: [PATCH 020/137] TEMP --- .../xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java | 8 +++++--- .../load/analysis.expected | 4 ++-- .../testDifferentTypesAcrossIndices/load/query.esql | 2 +- .../nullify/analysis.expected | 5 +++-- .../testDifferentTypesAcrossIndices/nullify/query.esql | 2 +- .../testDifferentTypesWithCast/load/analysis.expected | 6 +++--- .../testDifferentTypesWithCast/load/query.esql | 2 +- .../testDifferentTypesWithCast/nullify/analysis.expected | 6 +++--- .../testDifferentTypesWithCast/nullify/query.esql | 2 +- .../load/analysis.expected | 6 +++--- .../testPartiallyMappedFieldWithEval/load/query.esql | 2 +- .../nullify/analysis.expected | 8 ++++---- .../testPartiallyMappedFieldWithEval/nullify/query.esql | 2 +- 13 files changed, 29 insertions(+), 26 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java index 1d480c6701019..089a16a868bef 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -356,6 +356,8 @@ public void testTimeSeriesRateUnmapped() throws Exception { """); } + // TODO add one for text + public void testTimeSeriesFirstOverTimeUnmapped() throws Exception { runTests(""" TS k8s @@ -381,14 +383,14 @@ public void testPartiallyMappedFieldWithEval() throws Exception { runTests(""" FROM sample_data, partial_mapping_sample_data | EVAL x = COALESCE(unmapped_message, "missing") - | KEEP @timestamp, x + | KEEP @timestamp, x, does_not_exist """); } public void testDifferentTypesAcrossIndices() throws Exception { runTests(""" FROM sample_data, sample_data_ts_long - | KEEP @timestamp, message + | KEEP @timestamp, message, does_not_exist """); } @@ -396,7 +398,7 @@ public void testDifferentTypesWithCast() throws Exception { runTests(""" FROM sample_data, sample_data_ts_long | EVAL ts = @timestamp::STRING - | KEEP ts, message + | KEEP ts, message, does_not_exist """); } diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected index 60246e2a52c6f..12f12d30d6904 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Project[[!@timestamp, message{f}#0]] - \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#1, event_duration{f}#2, message{f}#0] \ No newline at end of file +\_Project[[!@timestamp, message{f}#0, does_not_exist{f}#1]] + \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#2, event_duration{f}#3, message{f}#0, does_not_exist{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/query.esql index 36f26bbad39a7..f8a423e9c25b6 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/query.esql @@ -1,2 +1,2 @@ SET unmapped_fields="load"; FROM sample_data, sample_data_ts_long -| KEEP @timestamp, message +| KEEP @timestamp, message, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected index 60246e2a52c6f..6666da83f0b7b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected @@ -1,3 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[!@timestamp, message{f}#0]] - \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#1, event_duration{f}#2, message{f}#0] \ No newline at end of file +\_Project[[!@timestamp, message{f}#0, does_not_exist{r}#1]] + \_Eval[[null[NULL] AS does_not_exist#1]] + \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#2, event_duration{f}#3, message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/query.esql index b469337a46ebc..4336bd5f39d8e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/query.esql @@ -1,2 +1,2 @@ SET unmapped_fields="nullify"; FROM sample_data, sample_data_ts_long -| KEEP @timestamp, message +| KEEP @timestamp, message, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected index c13045a018215..837e284d3469d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[ts{r}#0, message{f}#1]] - \_Eval[[$$@timestamp$converted_to$keyword{f$}#2 AS ts#0]] - \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#3, event_duration{f}#4, message{f}#1, $$@timestamp$converted_to$keyword{f$}#2] \ No newline at end of file +\_Project[[ts{r}#0, message{f}#1, does_not_exist{f}#2]] + \_Eval[[$$@timestamp$converted_to$keyword{f$}#3 AS ts#0]] + \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#4, event_duration{f}#5, message{f}#1, $$@timestamp$converted_to$keyword{f$}#3, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/query.esql index c739306c06b40..1ac50de7de6cd 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/query.esql @@ -1,3 +1,3 @@ SET unmapped_fields="load"; FROM sample_data, sample_data_ts_long | EVAL ts = @timestamp::STRING -| KEEP ts, message +| KEEP ts, message, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected index c13045a018215..07c96c69b56aa 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[ts{r}#0, message{f}#1]] - \_Eval[[$$@timestamp$converted_to$keyword{f$}#2 AS ts#0]] - \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#3, event_duration{f}#4, message{f}#1, $$@timestamp$converted_to$keyword{f$}#2] \ No newline at end of file +\_Project[[ts{r}#0, message{f}#1, does_not_exist{r}#2]] + \_Eval[[$$@timestamp$converted_to$keyword{f$}#3 AS ts#0, null[NULL] AS does_not_exist#2]] + \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#4, event_duration{f}#5, message{f}#1, $$@timestamp$converted_to$keyword{f$}#3] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql index 8a4145812c548..ab8c59e257e6d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql @@ -1,3 +1,3 @@ SET unmapped_fields="nullify"; FROM sample_data, sample_data_ts_long | EVAL ts = @timestamp::STRING -| KEEP ts, message +| KEEP ts, message, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected index c5c5603a87da1..b34196e39e72e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[@timestamp{f}#0, x{r}#1]] - \_Eval[[COALESCE(unmapped_message{f}#2,missing[KEYWORD]) AS x#1]] - \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#3, event_duration{f}#4, message{f}#5, unmapped_message{f}#2] \ No newline at end of file +\_Project[[@timestamp{f}#0, x{r}#1, does_not_exist{f}#2]] + \_Eval[[COALESCE(unmapped_message{f}#3,missing[KEYWORD]) AS x#1]] + \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6, unmapped_message{f}#3, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/query.esql index 3d56b92b85d47..578e1fcb86bb8 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/query.esql @@ -1,3 +1,3 @@ SET unmapped_fields="load"; FROM sample_data, partial_mapping_sample_data | EVAL x = COALESCE(unmapped_message, "missing") -| KEEP @timestamp, x +| KEEP @timestamp, x, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected index d41f33ebff73e..3423a5d39ac06 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected @@ -1,5 +1,5 @@ Limit[1000[INTEGER],false,false] -\_Project[[@timestamp{f}#0, x{r}#1]] - \_Eval[[COALESCE(unmapped_message{r}#2,missing[KEYWORD]) AS x#1]] - \_Eval[[null[NULL] AS unmapped_message#2]] - \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#3, event_duration{f}#4, message{f}#5] \ No newline at end of file +\_Project[[@timestamp{f}#0, x{r}#1, does_not_exist{r}#2]] + \_Eval[[COALESCE(unmapped_message{r}#3,missing[KEYWORD]) AS x#1]] + \_Eval[[null[NULL] AS unmapped_message#3, null[NULL] AS does_not_exist#2]] + \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/query.esql index b066c80c57f4d..8a34446c7a5cc 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/query.esql @@ -1,3 +1,3 @@ SET unmapped_fields="nullify"; FROM sample_data, partial_mapping_sample_data | EVAL x = COALESCE(unmapped_message, "missing") -| KEEP @timestamp, x +| KEEP @timestamp, x, does_not_exist From ac35237b9d554e0c12e6bc68cd8fcb33268fb52d Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 4 Feb 2026 14:10:06 +0200 Subject: [PATCH 021/137] Push after potentially unmapped field hack --- .../xpack/esql/core/expression/Attribute.java | 2 +- .../xpack/esql/core/expression/FieldAttribute.java | 11 +++++++++++ .../xpack/esql/core/tree/NodeUtils.java | 1 + .../testCoalesce/load/analysis.expected | 4 ++-- .../testCoalesce/nullify/analysis.expected | 4 ++-- .../load/analysis.expected | 2 +- .../nullify/analysis.expected | 2 +- .../load/analysis.expected | 4 ++-- .../nullify/analysis.expected | 4 ++-- .../testDrop/load/analysis.expected | 2 +- .../testDrop/nullify/analysis.expected | 2 +- .../testDropAndMatchingStar/load/analysis.expected | 2 +- .../nullify/analysis.expected | 2 +- .../testEvalAfterKeepStar/load/analysis.expected | 2 +- .../testEvalAfterKeepStar/nullify/analysis.expected | 2 +- .../load/analysis.expected | 2 +- .../nullify/analysis.expected | 2 +- .../testEvalAndKeep/load/analysis.expected | 2 +- .../testEvalCast/load/analysis.expected | 2 +- .../testEvalCastInPlace/load/analysis.expected | 2 +- .../testFork/load/analysis.expected | 4 ++-- .../testFork/nullify/analysis.expected | 4 ++-- .../testForkWithEval/load/analysis.expected | 4 ++-- .../testForkWithEval/nullify/analysis.expected | 4 ++-- .../testForkWithStats/load/analysis.expected | 6 +++--- .../testForkWithStats/nullify/analysis.expected | 2 +- .../testInlineStats/load/analysis.expected | 2 +- .../testInlineStats/nullify/analysis.expected | 2 +- .../testKeep/load/analysis.expected | 2 +- .../testKeepAndMatchingStar/load/analysis.expected | 2 +- .../nullify/analysis.expected | 2 +- .../testKeepRepeated/load/analysis.expected | 2 +- .../testKeepThenEval/load/analysis.expected | 2 +- .../testLookupJoin/load/analysis.expected | 4 ++-- .../testLookupJoin/nullify/analysis.expected | 2 +- .../testLookupJoinWithFilter/load/analysis.expected | 4 ++-- .../nullify/analysis.expected | 4 ++-- .../testMvExpand/load/analysis.expected | 2 +- .../testPartiallyMappedField/load/analysis.expected | 2 +- .../nullify/analysis.expected | 2 +- .../load/analysis.expected | 4 ++-- .../nullify/analysis.expected | 2 +- .../load/analysis.expected | 2 +- .../testRename/load/analysis.expected | 2 +- .../testRename/nullify/analysis.expected | 2 +- .../testRenameEval/load/analysis.expected | 2 +- .../testRenameEval/nullify/analysis.expected | 2 +- .../testRenameRepeated/load/analysis.expected | 2 +- .../testRenameRepeated/nullify/analysis.expected | 2 +- .../testSort/load/analysis.expected | 2 +- .../testSortMultiple/load/analysis.expected | 2 +- .../testSortMultiple/nullify/analysis.expected | 2 +- .../testStatsBy/load/analysis.expected | 2 +- .../testStatsCount/load/analysis.expected | 2 +- .../testStatsMultiple/load/analysis.expected | 2 +- .../testStatsMultiple/nullify/analysis.expected | 2 +- .../load/analysis.expected | 2 +- .../testStatsSumBy/load/analysis.expected | 2 +- .../testStatsSumByComplex/load/analysis.expected | 2 +- .../testStatsSumByComplex/nullify/analysis.expected | 2 +- .../testStatsSumByMultiple/load/analysis.expected | 2 +- .../testStatsSumByMultiple/nullify/analysis.expected | 2 +- .../load/analysis.expected | 6 +++--- .../nullify/analysis.expected | 6 +++--- .../testSubqueryKeepUnmapped/load/analysis.expected | 6 +++--- .../nullify/analysis.expected | 6 +++--- .../testSubqueryWithStats/load/analysis.expected | 6 +++--- .../testSubqueryWithStats/nullify/analysis.expected | 4 ++-- .../load/analysis.expected | 2 +- .../nullify/analysis.expected | 2 +- .../load/analysis.expected | 2 +- .../nullify/analysis.expected | 2 +- .../load/analysis.expected | 2 +- .../nullify/analysis.expected | 2 +- .../nullify/analysis.expected | 2 +- .../bucket/local_physical_optimization.expected | 12 ++++++------ .../date_trunc/local_physical_optimization.expected | 12 ++++++------ .../round_to/local_physical_optimization.expected | 12 ++++++------ .../bucket/local_physical_optimization.expected | 4 ++-- .../date_trunc/local_physical_optimization.expected | 4 ++-- .../round_to/local_physical_optimization.expected | 4 ++-- .../bucket/local_physical_optimization.expected | 6 +++--- .../date_trunc/local_physical_optimization.expected | 6 +++--- .../round_to/local_physical_optimization.expected | 6 +++--- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 2 +- .../bucket/local_physical_optimization.expected | 2 +- .../date_trunc/local_physical_optimization.expected | 2 +- .../round_to/local_physical_optimization.expected | 2 +- .../date_trunc/local_physical_optimization.expected | 10 +++++----- .../round_to/local_physical_optimization.expected | 10 +++++----- .../local_physical_optimization.expected | 12 ++++++------ .../local_physical_optimization.expected | 4 ++-- ...reduce_physical_optimization_data_driver.expected | 4 ++-- .../local_reduce_planned_data_driver.expected | 6 +++--- .../local_reduce_planned_reduce_driver.expected | 8 ++++---- .../physical_optimization.expected | 10 +++++----- ...reduce_physical_optimization_data_driver.expected | 4 ++-- .../local_reduce_planned_data_driver.expected | 4 ++-- .../local_reduce_planned_reduce_driver.expected | 6 +++--- .../physical_optimization.expected | 6 +++--- ...reduce_physical_optimization_data_driver.expected | 4 ++-- .../local_reduce_planned_data_driver.expected | 4 ++-- .../local_reduce_planned_reduce_driver.expected | 6 +++--- .../physical_optimization.expected | 6 +++--- ...reduce_physical_optimization_data_driver.expected | 10 +++++----- .../local_reduce_planned_data_driver.expected | 10 +++++----- .../local_reduce_planned_reduce_driver.expected | 8 ++++---- .../physical_optimization.expected | 12 ++++++------ ...reduce_physical_optimization_data_driver.expected | 4 ++-- .../local_reduce_planned_data_driver.expected | 6 +++--- .../local_reduce_planned_reduce_driver.expected | 8 ++++---- .../physical_optimization.expected | 10 +++++----- ...reduce_physical_optimization_data_driver.expected | 4 ++-- .../local_reduce_planned_data_driver.expected | 6 +++--- .../local_reduce_planned_reduce_driver.expected | 8 ++++---- .../testMultipleTopN/physical_optimization.expected | 12 ++++++------ ...reduce_physical_optimization_data_driver.expected | 10 +++++----- ...duce_physical_optimization_reduce_driver.expected | 6 +++--- .../local_reduce_planned_data_driver.expected | 10 +++++----- .../local_reduce_planned_reduce_driver.expected | 6 +++--- .../physical_optimization.expected | 12 ++++++------ ...reduce_physical_optimization_data_driver.expected | 4 ++-- .../local_reduce_planned_data_driver.expected | 6 +++--- .../local_reduce_planned_reduce_driver.expected | 8 ++++---- .../physical_optimization.expected | 10 +++++----- ...reduce_physical_optimization_data_driver.expected | 4 ++-- .../local_reduce_planned_data_driver.expected | 6 +++--- .../local_reduce_planned_reduce_driver.expected | 8 ++++---- .../physical_optimization.expected | 10 +++++----- ...reduce_physical_optimization_data_driver.expected | 4 ++-- .../local_reduce_planned_data_driver.expected | 6 +++--- .../local_reduce_planned_reduce_driver.expected | 8 ++++---- .../testTopNThenStats/physical_optimization.expected | 10 +++++----- ...reduce_physical_optimization_data_driver.expected | 4 ++-- .../local_reduce_planned_data_driver.expected | 6 +++--- .../local_reduce_planned_reduce_driver.expected | 8 ++++---- .../physical_optimization.expected | 10 +++++----- 142 files changed, 331 insertions(+), 319 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Attribute.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Attribute.java index 69233e86ef865..62cfd9786b0c7 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Attribute.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Attribute.java @@ -221,7 +221,7 @@ public String toString() { @Override public String nodeString(NodeStringFormat format) { - return toString(); + return toString(format); } protected abstract String label(); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/FieldAttribute.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/FieldAttribute.java index bd6377cfd109d..28dec3ad94a2a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/FieldAttribute.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/FieldAttribute.java @@ -271,4 +271,15 @@ public boolean isMetric() { public EsField field() { return field; } + + @Override + public String nodeString(NodeStringFormat format) { + return switch (format) { + // FIXME(gal, NOCOMMIT) unhack + case FULL -> Strings.format( + "%s{%s(%s)%s}#%s".formatted(qualifiedName(), label(), field.getWriteableName(), synthetic() ? "$" : "", id()) + ); + case LIMITED -> super.nodeString(format); + }; + } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/tree/NodeUtils.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/tree/NodeUtils.java index 6874b869ec872..ed453bedbacf6 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/tree/NodeUtils.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/tree/NodeUtils.java @@ -62,6 +62,7 @@ public static String diffString(String left, String right) { public static String toString(Collection c, Node.NodeStringFormat format) { return switch (format) { case LIMITED -> limitedToString(c); + // FIXME(gal, NOCOMMIT) This need to pass format to c as well case FULL -> unlimitedToString(c); }; } diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/analysis.expected index d3111b5b4cda6..e3749cf60fe6d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[emp_no{f}#0, x{r}#1]] - \_Eval[[COALESCE(TOLONG(does_not_exist{f}#2),TOLONG(emp_no{f}#0),TOLONG(0[INTEGER])) AS x#1]] +\_Project[[emp_no{f(EsField)}#0, x{r}#1]] + \_Eval[[COALESCE(TOLONG(does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2),TOLONG(emp_no{f(EsField)}#0),TOLONG(0[INTEGER])) AS x#1]] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#0, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist{f}#2, x{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/analysis.expected index 5cccb49a752cc..bcdfea953020a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/analysis.expected @@ -1,5 +1,5 @@ Limit[1000[INTEGER],false,false] -\_Project[[emp_no{f}#0, x{r}#1]] - \_Eval[[COALESCE(TOLONG(does_not_exist{r}#2),TOLONG(emp_no{f}#0),TOLONG(0[INTEGER])) AS x#1]] +\_Project[[emp_no{f(EsField)}#0, x{r}#1]] + \_Eval[[COALESCE(TOLONG(does_not_exist{r}#2),TOLONG(emp_no{f(EsField)}#0),TOLONG(0[INTEGER])) AS x#1]] \_Eval[[null[NULL] AS does_not_exist#2, null[NULL] AS x#3]] \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected index 12f12d30d6904..fa51740222109 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Project[[!@timestamp, message{f}#0, does_not_exist{f}#1]] +\_Project[[!@timestamp, message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1]] \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#2, event_duration{f}#3, message{f}#0, does_not_exist{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected index 6666da83f0b7b..b20e372050ebe 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[!@timestamp, message{f}#0, does_not_exist{r}#1]] +\_Project[[!@timestamp, message{f(KeywordEsField)}#0, does_not_exist{r}#1]] \_Eval[[null[NULL] AS does_not_exist#1]] \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#2, event_duration{f}#3, message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected index 837e284d3469d..4e22cfb0e1b0c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[ts{r}#0, message{f}#1, does_not_exist{f}#2]] - \_Eval[[$$@timestamp$converted_to$keyword{f$}#3 AS ts#0]] +\_Project[[ts{r}#0, message{f(KeywordEsField)}#1, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2]] + \_Eval[[$$@timestamp$converted_to$keyword{f(MultiTypeEsField)$}#3 AS ts#0]] \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#4, event_duration{f}#5, message{f}#1, $$@timestamp$converted_to$keyword{f$}#3, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected index 07c96c69b56aa..f280fa143e76e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[ts{r}#0, message{f}#1, does_not_exist{r}#2]] - \_Eval[[$$@timestamp$converted_to$keyword{f$}#3 AS ts#0, null[NULL] AS does_not_exist#2]] +\_Project[[ts{r}#0, message{f(KeywordEsField)}#1, does_not_exist{r}#2]] + \_Eval[[$$@timestamp$converted_to$keyword{f(MultiTypeEsField)$}#3 AS ts#0, null[NULL] AS does_not_exist#2]] \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#4, event_duration{f}#5, message{f}#1, $$@timestamp$converted_to$keyword{f$}#3] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected index f5ab73414c471..acd024f56f58a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21]] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, first_name{f(KeywordEsField)}#2, gender{f(KeywordEsField)}#3, height{f(EsField)}#4, height.float{f(EsField)}#5, height.half_float{f(EsField)}#6, height.scaled_float{f(EsField)}#7, hire_date{f(DateEsField)}#8, is_rehired{f(EsField)}#9, job_positions{f(KeywordEsField)}#10, languages{f(EsField)}#11, languages.byte{f(EsField)}#12, languages.long{f(EsField)}#13, languages.short{f(EsField)}#14, last_name{f(KeywordEsField)}#15, salary{f(EsField)}#16, salary_change{f(EsField)}#17, salary_change.int{f(EsField)}#18, salary_change.keyword{f(KeywordEsField)}#19, salary_change.long{f(EsField)}#20, still_hired{f(EsField)}#21]] \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#22, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21, does_not_exist_field{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected index 09d5818b5d458..9b31329838788 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21]] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, first_name{f(KeywordEsField)}#2, gender{f(KeywordEsField)}#3, height{f(EsField)}#4, height.float{f(EsField)}#5, height.half_float{f(EsField)}#6, height.scaled_float{f(EsField)}#7, hire_date{f(DateEsField)}#8, is_rehired{f(EsField)}#9, job_positions{f(KeywordEsField)}#10, languages{f(EsField)}#11, languages.byte{f(EsField)}#12, languages.long{f(EsField)}#13, languages.short{f(EsField)}#14, last_name{f(KeywordEsField)}#15, salary{f(EsField)}#16, salary_change{f(EsField)}#17, salary_change.int{f(EsField)}#18, salary_change.keyword{f(KeywordEsField)}#19, salary_change.long{f(EsField)}#20, still_hired{f(EsField)}#21]] \_Eval[[null[NULL] AS does_not_exist_field#22]] \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#23, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected index f5ab73414c471..acd024f56f58a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21]] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, first_name{f(KeywordEsField)}#2, gender{f(KeywordEsField)}#3, height{f(EsField)}#4, height.float{f(EsField)}#5, height.half_float{f(EsField)}#6, height.scaled_float{f(EsField)}#7, hire_date{f(DateEsField)}#8, is_rehired{f(EsField)}#9, job_positions{f(KeywordEsField)}#10, languages{f(EsField)}#11, languages.byte{f(EsField)}#12, languages.long{f(EsField)}#13, languages.short{f(EsField)}#14, last_name{f(KeywordEsField)}#15, salary{f(EsField)}#16, salary_change{f(EsField)}#17, salary_change.int{f(EsField)}#18, salary_change.keyword{f(KeywordEsField)}#19, salary_change.long{f(EsField)}#20, still_hired{f(EsField)}#21]] \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#22, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21, does_not_exist_field{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected index 09d5818b5d458..9b31329838788 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21]] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, first_name{f(KeywordEsField)}#2, gender{f(KeywordEsField)}#3, height{f(EsField)}#4, height.float{f(EsField)}#5, height.half_float{f(EsField)}#6, height.scaled_float{f(EsField)}#7, hire_date{f(DateEsField)}#8, is_rehired{f(EsField)}#9, job_positions{f(KeywordEsField)}#10, languages{f(EsField)}#11, languages.byte{f(EsField)}#12, languages.long{f(EsField)}#13, languages.short{f(EsField)}#14, last_name{f(KeywordEsField)}#15, salary{f(EsField)}#16, salary_change{f(EsField)}#17, salary_change.int{f(EsField)}#18, salary_change.keyword{f(KeywordEsField)}#19, salary_change.long{f(EsField)}#20, still_hired{f(EsField)}#21]] \_Eval[[null[NULL] AS does_not_exist_field#22]] \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#23, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/analysis.expected index fffeff38bda8f..8f5d075d36aaf 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/analysis.expected @@ -1,5 +1,5 @@ Limit[1000[INTEGER],false,false] \_Eval[[TODOUBLE(does_not_exist_field{f}#0) + 2[INTEGER] AS y#1]] \_Eval[[emp_no{f}#2 + 1[INTEGER] AS x#3]] - \_Project[[avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{f}#0]] + \_Project[[avg_worked_seconds{f(EsField)}#4, birth_date{f(DateEsField)}#5, emp_no{f(EsField)}#2, first_name{f(KeywordEsField)}#6, gender{f(KeywordEsField)}#7, height{f(EsField)}#8, height.float{f(EsField)}#9, height.half_float{f(EsField)}#10, height.scaled_float{f(EsField)}#11, hire_date{f(DateEsField)}#12, is_rehired{f(EsField)}#13, job_positions{f(KeywordEsField)}#14, languages{f(EsField)}#15, languages.byte{f(EsField)}#16, languages.long{f(EsField)}#17, languages.short{f(EsField)}#18, last_name{f(KeywordEsField)}#19, salary{f(EsField)}#20, salary_change{f(EsField)}#21, salary_change.int{f(EsField)}#22, salary_change.keyword{f(KeywordEsField)}#23, salary_change.long{f(EsField)}#24, still_hired{f(EsField)}#25, does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0]] \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/analysis.expected index 8a7ed2a845200..2b90aac6121b2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/analysis.expected @@ -1,6 +1,6 @@ Limit[1000[INTEGER],false,false] \_Eval[[TODOUBLE(does_not_exist_field{r}#0) + 2[INTEGER] AS y#1]] \_Eval[[emp_no{f}#2 + 1[INTEGER] AS x#3]] - \_Project[[avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{r}#0]] + \_Project[[avg_worked_seconds{f(EsField)}#4, birth_date{f(DateEsField)}#5, emp_no{f(EsField)}#2, first_name{f(KeywordEsField)}#6, gender{f(KeywordEsField)}#7, height{f(EsField)}#8, height.float{f(EsField)}#9, height.half_float{f(EsField)}#10, height.scaled_float{f(EsField)}#11, hire_date{f(DateEsField)}#12, is_rehired{f(EsField)}#13, job_positions{f(KeywordEsField)}#14, languages{f(EsField)}#15, languages.byte{f(EsField)}#16, languages.long{f(EsField)}#17, languages.short{f(EsField)}#18, last_name{f(KeywordEsField)}#19, salary{f(EsField)}#20, salary_change{f(EsField)}#21, salary_change.int{f(EsField)}#22, salary_change.keyword{f(KeywordEsField)}#23, salary_change.long{f(EsField)}#24, still_hired{f(EsField)}#25, does_not_exist_field{r}#0]] \_Eval[[null[NULL] AS does_not_exist_field#0]] \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/analysis.expected index 985d0ddb1a1f7..14e653fae9924 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/analysis.expected @@ -1,5 +1,5 @@ Limit[1000[INTEGER],false,false] \_Eval[[TODOUBLE(emp_does_not_exist_field{f}#0) + 2[INTEGER] AS y#1]] \_Eval[[emp_no{f}#2 + 1[INTEGER] AS x#3]] - \_Project[[emp_no{f}#2, avg_worked_seconds{f}#4, birth_date{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, emp_does_not_exist_field{f}#0]] + \_Project[[emp_no{f(EsField)}#2, avg_worked_seconds{f(EsField)}#4, birth_date{f(DateEsField)}#5, first_name{f(KeywordEsField)}#6, gender{f(KeywordEsField)}#7, height{f(EsField)}#8, height.float{f(EsField)}#9, height.half_float{f(EsField)}#10, height.scaled_float{f(EsField)}#11, hire_date{f(DateEsField)}#12, is_rehired{f(EsField)}#13, job_positions{f(KeywordEsField)}#14, languages{f(EsField)}#15, languages.byte{f(EsField)}#16, languages.long{f(EsField)}#17, languages.short{f(EsField)}#18, last_name{f(KeywordEsField)}#19, salary{f(EsField)}#20, salary_change{f(EsField)}#21, salary_change.int{f(EsField)}#22, salary_change.keyword{f(KeywordEsField)}#23, salary_change.long{f(EsField)}#24, still_hired{f(EsField)}#25, emp_does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0]] \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, emp_does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/analysis.expected index c85c64472a028..87cf671c0534f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/analysis.expected @@ -1,6 +1,6 @@ Limit[1000[INTEGER],false,false] \_Eval[[TODOUBLE(emp_does_not_exist_field{r}#0) + 2[INTEGER] AS y#1]] \_Eval[[emp_no{f}#2 + 1[INTEGER] AS x#3]] - \_Project[[emp_no{f}#2, avg_worked_seconds{f}#4, birth_date{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, emp_does_not_exist_field{r}#0]] + \_Project[[emp_no{f(EsField)}#2, avg_worked_seconds{f(EsField)}#4, birth_date{f(DateEsField)}#5, first_name{f(KeywordEsField)}#6, gender{f(KeywordEsField)}#7, height{f(EsField)}#8, height.float{f(EsField)}#9, height.half_float{f(EsField)}#10, height.scaled_float{f(EsField)}#11, hire_date{f(DateEsField)}#12, is_rehired{f(EsField)}#13, job_positions{f(KeywordEsField)}#14, languages{f(EsField)}#15, languages.byte{f(EsField)}#16, languages.long{f(EsField)}#17, languages.short{f(EsField)}#18, last_name{f(KeywordEsField)}#19, salary{f(EsField)}#20, salary_change{f(EsField)}#21, salary_change.int{f(EsField)}#22, salary_change.keyword{f(KeywordEsField)}#23, salary_change.long{f(EsField)}#24, still_hired{f(EsField)}#25, emp_does_not_exist_field{r}#0]] \_Eval[[null[NULL] AS emp_does_not_exist_field#0]] \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/analysis.expected index 5577ec2723da6..9639c04a04474 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[does_not_exist_field1{f}#0, does_not_exist_field2{f}#1]] +\_Project[[does_not_exist_field1{f(PotentiallyUnmappedKeywordEsField)}#0, does_not_exist_field2{f(PotentiallyUnmappedKeywordEsField)}#1]] \_Eval[[TOINTEGER(does_not_exist_field1{f}#0) + 42[INTEGER] AS x#2]] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field1{f}#0, does_not_exist_field2{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected index 11402fc799020..93fe00d388c1d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Eval[[TOLONG(does_not_exist_field{f}#0) AS x#1]] +\_Eval[[TOLONG(does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0) AS x#1]] \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected index 81f2f5801c839..1057b571c78de 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Eval[[TOLONG(does_not_exist_field{f}#0) AS does_not_exist_field::LONG#1]] +\_Eval[[TOLONG(does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0) AS does_not_exist_field::LONG#1]] \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected index 8c02caed8fa2b..1ea65e9515a9e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected @@ -1,12 +1,12 @@ Limit[1000[INTEGER],false,false] \_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, _fork{r}#24]] |_Limit[1000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, does_not_exist{f}#48, _fork{r}#49]] + | \_Project[[avg_worked_seconds{f(EsField)}#25, birth_date{f(DateEsField)}#26, emp_no{f(EsField)}#27, first_name{f(KeywordEsField)}#28, gender{f(KeywordEsField)}#29, height{f(EsField)}#30, height.float{f(EsField)}#31, height.half_float{f(EsField)}#32, height.scaled_float{f(EsField)}#33, hire_date{f(DateEsField)}#34, is_rehired{f(EsField)}#35, job_positions{f(KeywordEsField)}#36, languages{f(EsField)}#37, languages.byte{f(EsField)}#38, languages.long{f(EsField)}#39, languages.short{f(EsField)}#40, last_name{f(KeywordEsField)}#41, salary{f(EsField)}#42, salary_change{f(EsField)}#43, salary_change.int{f(EsField)}#44, salary_change.keyword{f(KeywordEsField)}#45, salary_change.long{f(EsField)}#46, still_hired{f(EsField)}#47, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#48, _fork{r}#49]] | \_Eval[[fork1[KEYWORD] AS _fork#49]] | \_Filter[TOLONG(does_not_exist{f}#48) > 0[INTEGER]] | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, does_not_exist{f}#48] \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f}#50, birth_date{f}#51, emp_no{f}#52, first_name{f}#53, gender{f}#54, height{f}#55, height.float{f}#56, height.half_float{f}#57, height.scaled_float{f}#58, hire_date{f}#59, is_rehired{f}#60, job_positions{f}#61, languages{f}#62, languages.byte{f}#63, languages.long{f}#64, languages.short{f}#65, last_name{f}#66, salary{f}#67, salary_change{f}#68, salary_change.int{f}#69, salary_change.keyword{f}#70, salary_change.long{f}#71, still_hired{f}#72, does_not_exist{r}#73, _fork{r}#49]] + \_Project[[avg_worked_seconds{f(EsField)}#50, birth_date{f(DateEsField)}#51, emp_no{f(EsField)}#52, first_name{f(KeywordEsField)}#53, gender{f(KeywordEsField)}#54, height{f(EsField)}#55, height.float{f(EsField)}#56, height.half_float{f(EsField)}#57, height.scaled_float{f(EsField)}#58, hire_date{f(DateEsField)}#59, is_rehired{f(EsField)}#60, job_positions{f(KeywordEsField)}#61, languages{f(EsField)}#62, languages.byte{f(EsField)}#63, languages.long{f(EsField)}#64, languages.short{f(EsField)}#65, last_name{f(KeywordEsField)}#66, salary{f(EsField)}#67, salary_change{f(EsField)}#68, salary_change.int{f(EsField)}#69, salary_change.keyword{f(KeywordEsField)}#70, salary_change.long{f(EsField)}#71, still_hired{f(EsField)}#72, does_not_exist{r}#73, _fork{r}#49]] \_Eval[[null[KEYWORD] AS does_not_exist#73]] \_Eval[[fork2[KEYWORD] AS _fork#49]] \_Filter[emp_no{f}#52 > 0[INTEGER]] diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/analysis.expected index 126b23315f762..bef6a1204b623 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/analysis.expected @@ -1,13 +1,13 @@ Limit[1000[INTEGER],false,false] \_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, _fork{r}#24]] |_Limit[1000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, does_not_exist{r}#48, _fork{r}#49]] + | \_Project[[avg_worked_seconds{f(EsField)}#25, birth_date{f(DateEsField)}#26, emp_no{f(EsField)}#27, first_name{f(KeywordEsField)}#28, gender{f(KeywordEsField)}#29, height{f(EsField)}#30, height.float{f(EsField)}#31, height.half_float{f(EsField)}#32, height.scaled_float{f(EsField)}#33, hire_date{f(DateEsField)}#34, is_rehired{f(EsField)}#35, job_positions{f(KeywordEsField)}#36, languages{f(EsField)}#37, languages.byte{f(EsField)}#38, languages.long{f(EsField)}#39, languages.short{f(EsField)}#40, last_name{f(KeywordEsField)}#41, salary{f(EsField)}#42, salary_change{f(EsField)}#43, salary_change.int{f(EsField)}#44, salary_change.keyword{f(KeywordEsField)}#45, salary_change.long{f(EsField)}#46, still_hired{f(EsField)}#47, does_not_exist{r}#48, _fork{r}#49]] | \_Eval[[fork1[KEYWORD] AS _fork#49]] | \_Filter[TOLONG(does_not_exist{r}#48) > 0[INTEGER]] | \_Eval[[null[NULL] AS does_not_exist#48]] | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f}#50, birth_date{f}#51, emp_no{f}#52, first_name{f}#53, gender{f}#54, height{f}#55, height.float{f}#56, height.half_float{f}#57, height.scaled_float{f}#58, hire_date{f}#59, is_rehired{f}#60, job_positions{f}#61, languages{f}#62, languages.byte{f}#63, languages.long{f}#64, languages.short{f}#65, last_name{f}#66, salary{f}#67, salary_change{f}#68, salary_change.int{f}#69, salary_change.keyword{f}#70, salary_change.long{f}#71, still_hired{f}#72, does_not_exist{r}#73, _fork{r}#49]] + \_Project[[avg_worked_seconds{f(EsField)}#50, birth_date{f(DateEsField)}#51, emp_no{f(EsField)}#52, first_name{f(KeywordEsField)}#53, gender{f(KeywordEsField)}#54, height{f(EsField)}#55, height.float{f(EsField)}#56, height.half_float{f(EsField)}#57, height.scaled_float{f(EsField)}#58, hire_date{f(DateEsField)}#59, is_rehired{f(EsField)}#60, job_positions{f(KeywordEsField)}#61, languages{f(EsField)}#62, languages.byte{f(EsField)}#63, languages.long{f(EsField)}#64, languages.short{f(EsField)}#65, last_name{f(KeywordEsField)}#66, salary{f(EsField)}#67, salary_change{f(EsField)}#68, salary_change.int{f(EsField)}#69, salary_change.keyword{f(KeywordEsField)}#70, salary_change.long{f(EsField)}#71, still_hired{f(EsField)}#72, does_not_exist{r}#73, _fork{r}#49]] \_Eval[[null[NULL] AS does_not_exist#73]] \_Eval[[fork2[KEYWORD] AS _fork#49]] \_Filter[emp_no{f}#52 > 0[INTEGER]] diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected index 96d5b43c3eb3b..312bfbd84c8b9 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected @@ -1,13 +1,13 @@ Limit[1000[INTEGER],false,false] \_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, x{r}#24, _fork{r}#25, y{r}#26]] |_Limit[1000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, does_not_exist{f}#50, x{r}#51, _fork{r}#52, y{r}#53]] + | \_Project[[avg_worked_seconds{f(EsField)}#27, birth_date{f(DateEsField)}#28, emp_no{f(EsField)}#29, first_name{f(KeywordEsField)}#30, gender{f(KeywordEsField)}#31, height{f(EsField)}#32, height.float{f(EsField)}#33, height.half_float{f(EsField)}#34, height.scaled_float{f(EsField)}#35, hire_date{f(DateEsField)}#36, is_rehired{f(EsField)}#37, job_positions{f(KeywordEsField)}#38, languages{f(EsField)}#39, languages.byte{f(EsField)}#40, languages.long{f(EsField)}#41, languages.short{f(EsField)}#42, last_name{f(KeywordEsField)}#43, salary{f(EsField)}#44, salary_change{f(EsField)}#45, salary_change.int{f(EsField)}#46, salary_change.keyword{f(KeywordEsField)}#47, salary_change.long{f(EsField)}#48, still_hired{f(EsField)}#49, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#50, x{r}#51, _fork{r}#52, y{r}#53]] | \_Eval[[null[INTEGER] AS y#53]] | \_Eval[[fork1[KEYWORD] AS _fork#52]] | \_Eval[[TODOUBLE(does_not_exist{f}#50) + 1[INTEGER] AS x#51]] | \_EsRelation[employees][avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, does_not_exist{f}#50] \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f}#54, birth_date{f}#55, emp_no{f}#56, first_name{f}#57, gender{f}#58, height{f}#59, height.float{f}#60, height.half_float{f}#61, height.scaled_float{f}#62, hire_date{f}#63, is_rehired{f}#64, job_positions{f}#65, languages{f}#66, languages.byte{f}#67, languages.long{f}#68, languages.short{f}#69, last_name{f}#70, salary{f}#71, salary_change{f}#72, salary_change.int{f}#73, salary_change.keyword{f}#74, salary_change.long{f}#75, still_hired{f}#76, does_not_exist{r}#77, x{r}#78, _fork{r}#52, y{r}#79]] + \_Project[[avg_worked_seconds{f(EsField)}#54, birth_date{f(DateEsField)}#55, emp_no{f(EsField)}#56, first_name{f(KeywordEsField)}#57, gender{f(KeywordEsField)}#58, height{f(EsField)}#59, height.float{f(EsField)}#60, height.half_float{f(EsField)}#61, height.scaled_float{f(EsField)}#62, hire_date{f(DateEsField)}#63, is_rehired{f(EsField)}#64, job_positions{f(KeywordEsField)}#65, languages{f(EsField)}#66, languages.byte{f(EsField)}#67, languages.long{f(EsField)}#68, languages.short{f(EsField)}#69, last_name{f(KeywordEsField)}#70, salary{f(EsField)}#71, salary_change{f(EsField)}#72, salary_change.int{f(EsField)}#73, salary_change.keyword{f(KeywordEsField)}#74, salary_change.long{f(EsField)}#75, still_hired{f(EsField)}#76, does_not_exist{r}#77, x{r}#78, _fork{r}#52, y{r}#79]] \_Eval[[null[KEYWORD] AS does_not_exist#77, null[DOUBLE] AS x#78]] \_Eval[[fork2[KEYWORD] AS _fork#52]] \_Eval[[emp_no{f}#56 + 1[INTEGER] AS y#79]] diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/analysis.expected index 745bf77c8febb..c02033434bdb1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/analysis.expected @@ -1,14 +1,14 @@ Limit[1000[INTEGER],false,false] \_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, x{r}#24, _fork{r}#25, y{r}#26]] |_Limit[1000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, does_not_exist{r}#50, x{r}#51, _fork{r}#52, y{r}#53]] + | \_Project[[avg_worked_seconds{f(EsField)}#27, birth_date{f(DateEsField)}#28, emp_no{f(EsField)}#29, first_name{f(KeywordEsField)}#30, gender{f(KeywordEsField)}#31, height{f(EsField)}#32, height.float{f(EsField)}#33, height.half_float{f(EsField)}#34, height.scaled_float{f(EsField)}#35, hire_date{f(DateEsField)}#36, is_rehired{f(EsField)}#37, job_positions{f(KeywordEsField)}#38, languages{f(EsField)}#39, languages.byte{f(EsField)}#40, languages.long{f(EsField)}#41, languages.short{f(EsField)}#42, last_name{f(KeywordEsField)}#43, salary{f(EsField)}#44, salary_change{f(EsField)}#45, salary_change.int{f(EsField)}#46, salary_change.keyword{f(KeywordEsField)}#47, salary_change.long{f(EsField)}#48, still_hired{f(EsField)}#49, does_not_exist{r}#50, x{r}#51, _fork{r}#52, y{r}#53]] | \_Eval[[null[INTEGER] AS y#53]] | \_Eval[[fork1[KEYWORD] AS _fork#52]] | \_Eval[[TODOUBLE(does_not_exist{r}#50) + 1[INTEGER] AS x#51]] | \_Eval[[null[NULL] AS does_not_exist#50]] | \_EsRelation[employees][avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49] \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f}#54, birth_date{f}#55, emp_no{f}#56, first_name{f}#57, gender{f}#58, height{f}#59, height.float{f}#60, height.half_float{f}#61, height.scaled_float{f}#62, hire_date{f}#63, is_rehired{f}#64, job_positions{f}#65, languages{f}#66, languages.byte{f}#67, languages.long{f}#68, languages.short{f}#69, last_name{f}#70, salary{f}#71, salary_change{f}#72, salary_change.int{f}#73, salary_change.keyword{f}#74, salary_change.long{f}#75, still_hired{f}#76, does_not_exist{r}#77, x{r}#78, _fork{r}#52, y{r}#79]] + \_Project[[avg_worked_seconds{f(EsField)}#54, birth_date{f(DateEsField)}#55, emp_no{f(EsField)}#56, first_name{f(KeywordEsField)}#57, gender{f(KeywordEsField)}#58, height{f(EsField)}#59, height.float{f(EsField)}#60, height.half_float{f(EsField)}#61, height.scaled_float{f(EsField)}#62, hire_date{f(DateEsField)}#63, is_rehired{f(EsField)}#64, job_positions{f(KeywordEsField)}#65, languages{f(EsField)}#66, languages.byte{f(EsField)}#67, languages.long{f(EsField)}#68, languages.short{f(EsField)}#69, last_name{f(KeywordEsField)}#70, salary{f(EsField)}#71, salary_change{f(EsField)}#72, salary_change.int{f(EsField)}#73, salary_change.keyword{f(KeywordEsField)}#74, salary_change.long{f(EsField)}#75, still_hired{f(EsField)}#76, does_not_exist{r}#77, x{r}#78, _fork{r}#52, y{r}#79]] \_Eval[[null[NULL] AS does_not_exist#77, null[DOUBLE] AS x#78]] \_Eval[[fork2[KEYWORD] AS _fork#52]] \_Eval[[emp_no{f}#56 + 1[INTEGER] AS y#79]] diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected index 179c4819647d5..3c38b14082b60 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected @@ -2,14 +2,14 @@ Limit[1000[INTEGER],false,false] \_OrderBy[[Order[does_not_exist{r}#0,ASC,LAST]]] \_Fork[[c{r}#1, does_not_exist{r}#0, _fork{r}#2, d{r}#3]] |_Limit[1000[INTEGER],false,false] - | \_Project[[c{r}#4, does_not_exist{f}#5, _fork{r}#6, d{r}#7]] + | \_Project[[c{r}#4, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#5, _fork{r}#6, d{r}#7]] | \_Eval[[null[DOUBLE] AS d#7]] | \_Eval[[fork1[KEYWORD] AS _fork#6]] - | \_Aggregate[[does_not_exist{f}#5],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist{f}#5]] + | \_Aggregate[[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#5],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#5]] | \_EsRelation[employees][avg_worked_seconds{f}#8, birth_date{f}#9, emp_no{f}#10, first_name{f}#11, gender{f}#12, height{f}#13, height.float{f}#14, height.half_float{f}#15, height.scaled_float{f}#16, hire_date{f}#17, is_rehired{f}#18, job_positions{f}#19, languages{f}#20, languages.byte{f}#21, languages.long{f}#22, languages.short{f}#23, last_name{f}#24, salary{f}#25, salary_change{f}#26, salary_change.int{f}#27, salary_change.keyword{f}#28, salary_change.long{f}#29, still_hired{f}#30, does_not_exist{f}#5] \_Limit[1000[INTEGER],false,false] \_Project[[c{r}#31, does_not_exist{r}#32, _fork{r}#6, d{r}#33]] \_Eval[[null[LONG] AS c#31, null[KEYWORD] AS does_not_exist#32]] \_Eval[[fork2[KEYWORD] AS _fork#6]] - \_Aggregate[[],[AVG(TODOUBLE(salary{f}#34),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS d#33]] + \_Aggregate[[],[AVG(TODOUBLE(salary{f(EsField)}#34),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS d#33]] \_EsRelation[employees][avg_worked_seconds{f}#35, birth_date{f}#36, emp_no{f}#37, first_name{f}#38, gender{f}#39, height{f}#40, height.float{f}#41, height.half_float{f}#42, height.scaled_float{f}#43, hire_date{f}#44, is_rehired{f}#45, job_positions{f}#46, languages{f}#47, languages.byte{f}#48, languages.long{f}#49, languages.short{f}#50, last_name{f}#51, salary{f}#34, salary_change{f}#52, salary_change.int{f}#53, salary_change.keyword{f}#54, salary_change.long{f}#55, still_hired{f}#56] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/analysis.expected index 0905fb72ef867..2b609c20b89e9 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/analysis.expected @@ -12,5 +12,5 @@ Limit[1000[INTEGER],false,false] \_Project[[c{r}#31, does_not_exist{r}#32, _fork{r}#6, d{r}#33]] \_Eval[[null[LONG] AS c#31, null[NULL] AS does_not_exist#32]] \_Eval[[fork2[KEYWORD] AS _fork#6]] - \_Aggregate[[],[AVG(TODOUBLE(salary{f}#34),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS d#33]] + \_Aggregate[[],[AVG(TODOUBLE(salary{f(EsField)}#34),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS d#33]] \_EsRelation[employees][avg_worked_seconds{f}#35, birth_date{f}#36, emp_no{f}#37, first_name{f}#38, gender{f}#39, height{f}#40, height.float{f}#41, height.half_float{f}#42, height.scaled_float{f}#43, hire_date{f}#44, is_rehired{f}#45, job_positions{f}#46, languages{f}#47, languages.byte{f}#48, languages.long{f}#49, languages.short{f}#50, last_name{f}#51, salary{f}#34, salary_change{f}#52, salary_change.int{f}#53, salary_change.keyword{f}#54, salary_change.long{f}#55, still_hired{f}#56] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected index 36814b4fcb812..0507eaa2c2446 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] \_InlineStats[] - \_Aggregate[[does_not_exist2{f}#0, emp_no{f}#1],[SUM(TODOUBLE(does_not_exist1{f}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{f}#0, emp_no{f}#1]] + \_Aggregate[[does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0, emp_no{f(EsField)}#1],[SUM(TODOUBLE(does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0, emp_no{f(EsField)}#1]] \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#1, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26, does_not_exist2{f}#0, does_not_exist1{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected index 5f2ab1697cd95..3d44e8346ff78 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected @@ -1,5 +1,5 @@ Limit[1000[INTEGER],false,false] \_InlineStats[] - \_Aggregate[[does_not_exist2{r}#0, emp_no{f}#1],[SUM(TODOUBLE(does_not_exist1{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{r}#0, emp_no{f}#1]] + \_Aggregate[[does_not_exist2{r}#0, emp_no{f(EsField)}#1],[SUM(TODOUBLE(does_not_exist1{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{r}#0, emp_no{f(EsField)}#1]] \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist1#2]] \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#1, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected index b0d320e2b8ee8..d21ff127af792 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Project[[does_not_exist_field{f}#0]] +\_Project[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0]] \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/analysis.expected index 872c7642ff1f5..31f790943f6fd 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Project[[emp_no{f}#0, does_not_exist_field{f}#1]] +\_Project[[emp_no{f(EsField)}#0, does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#1]] \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#0, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/analysis.expected index cc66e19745707..7b3dd01202d22 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[emp_no{f}#0, does_not_exist_field{r}#1]] +\_Project[[emp_no{f(EsField)}#0, does_not_exist_field{r}#1]] \_Eval[[null[NULL] AS does_not_exist_field#1]] \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#0, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/analysis.expected index b0d320e2b8ee8..d21ff127af792 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Project[[does_not_exist_field{f}#0]] +\_Project[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0]] \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected index c6a21f8491422..01fc4148688e2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] \_Eval[[42[INTEGER] AS does_not_exist_field#0]] - \_Project[[does_not_exist_field{f}#1]] + \_Project[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#1]] \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected index f57fe6df9c0a7..92f45cdd558bd 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected @@ -1,5 +1,5 @@ Limit[1000[INTEGER],false,false] -\_LookupJoin[LEFT,[language_code{r}#0],[language_code{f}#1],false,null] - |_Eval[[TOINTEGER(does_not_exist{f}#2) AS language_code#0]] +\_LookupJoin[LEFT,[language_code{r}#0],[language_code{f(EsField)}#1],false,null] + |_Eval[[TOINTEGER(does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2) AS language_code#0]] | \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#2] \_EsRelation[languages_lookup][LOOKUP][language_code{f}#1, language_name{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/analysis.expected index 8a2b4eaf82e13..a6ffe3dba751f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/analysis.expected @@ -1,5 +1,5 @@ Limit[1000[INTEGER],false,false] -\_LookupJoin[LEFT,[language_code{r}#0],[language_code{f}#1],false,null] +\_LookupJoin[LEFT,[language_code{r}#0],[language_code{f(EsField)}#1],false,null] |_Eval[[TOINTEGER(does_not_exist{r}#2) AS language_code#0]] | \_Eval[[null[NULL] AS does_not_exist#2]] | \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected index 0e429b6f7e085..89dfad1b7ef36 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected @@ -1,6 +1,6 @@ Limit[1000[INTEGER],false,false] \_Filter[TOLONG(does_not_exist{f}#0) > 0[INTEGER]] - \_LookupJoin[LEFT,[language_code{r}#1],[language_code{f}#2],false,null] - |_Eval[[languages{f}#3 AS language_code#1]] + \_LookupJoin[LEFT,[language_code{r}#1],[language_code{f(EsField)}#2],false,null] + |_Eval[[languages{f(EsField)}#3 AS language_code#1]] | \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#3, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#0] \_EsRelation[languages_lookup][LOOKUP][language_code{f}#2, language_name{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/analysis.expected index 204ffb0063c39..b67ae7d9398f2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/analysis.expected @@ -1,7 +1,7 @@ Limit[1000[INTEGER],false,false] \_Filter[TOLONG(does_not_exist{r}#0) > 0[INTEGER]] - \_LookupJoin[LEFT,[language_code{r}#1],[language_code{f}#2],false,null] - |_Eval[[languages{f}#3 AS language_code#1, null[NULL] AS does_not_exist#4]] + \_LookupJoin[LEFT,[language_code{r}#1],[language_code{f(EsField)}#2],false,null] + |_Eval[[languages{f(EsField)}#3 AS language_code#1, null[NULL] AS does_not_exist#4]] | \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#7, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#3, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26] \_Eval[[null[NULL] AS does_not_exist#0]] \_EsRelation[languages_lookup][LOOKUP][language_code{f}#2, language_name{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/analysis.expected index 431d39d786c87..16c852fe171c6 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_MvExpand[does_not_exist{f}#0,does_not_exist{r}#1] +\_MvExpand[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#0,does_not_exist{r}#1] \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/analysis.expected index 09d01f355c3bc..6491d2ecb54e7 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Project[[@timestamp{f}#0, message{f}#1, unmapped_message{f}#2]] +\_Project[[@timestamp{f(DateEsField)}#0, message{f(KeywordEsField)}#1, unmapped_message{f(PotentiallyUnmappedKeywordEsField)}#2]] \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#3, event_duration{f}#4, message{f}#1, unmapped_message{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/analysis.expected index c23e90cb6e10b..b637cc104c27c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[@timestamp{f}#0, message{f}#1, unmapped_message{r}#2]] +\_Project[[@timestamp{f(DateEsField)}#0, message{f(KeywordEsField)}#1, unmapped_message{r}#2]] \_Eval[[null[NULL] AS unmapped_message#2]] \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#3, event_duration{f}#4, message{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected index b34196e39e72e..056d8546be64a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[@timestamp{f}#0, x{r}#1, does_not_exist{f}#2]] - \_Eval[[COALESCE(unmapped_message{f}#3,missing[KEYWORD]) AS x#1]] +\_Project[[@timestamp{f(DateEsField)}#0, x{r}#1, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2]] + \_Eval[[COALESCE(unmapped_message{f(PotentiallyUnmappedKeywordEsField)}#3,missing[KEYWORD]) AS x#1]] \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6, unmapped_message{f}#3, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected index 3423a5d39ac06..e32df7a3a8f8d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected @@ -1,5 +1,5 @@ Limit[1000[INTEGER],false,false] -\_Project[[@timestamp{f}#0, x{r}#1, does_not_exist{r}#2]] +\_Project[[@timestamp{f(DateEsField)}#0, x{r}#1, does_not_exist{r}#2]] \_Eval[[COALESCE(unmapped_message{r}#3,missing[KEYWORD]) AS x#1]] \_Eval[[null[NULL] AS unmapped_message#3, null[NULL] AS does_not_exist#2]] \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/analysis.expected index 30aecb7154ced..a3725a08f77a4 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[unmapped_message{f}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#1, unmapped_message{f}#0]] +\_Aggregate[[unmapped_message{f(PotentiallyUnmappedKeywordEsField)}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#1, unmapped_message{f(PotentiallyUnmappedKeywordEsField)}#0]] \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#5, unmapped_message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/analysis.expected index d593728177af5..fc6e42d4dce53 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2 AS employee_number#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#24 AS now_it_does#25]] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2 AS employee_number#3, first_name{f(KeywordEsField)}#4, gender{f(KeywordEsField)}#5, height{f(EsField)}#6, height.float{f(EsField)}#7, height.half_float{f(EsField)}#8, height.scaled_float{f(EsField)}#9, hire_date{f(DateEsField)}#10, is_rehired{f(EsField)}#11, job_positions{f(KeywordEsField)}#12, languages{f(EsField)}#13, languages.byte{f(EsField)}#14, languages.long{f(EsField)}#15, languages.short{f(EsField)}#16, last_name{f(KeywordEsField)}#17, salary{f(EsField)}#18, salary_change{f(EsField)}#19, salary_change.int{f(EsField)}#20, salary_change.keyword{f(KeywordEsField)}#21, salary_change.long{f(EsField)}#22, still_hired{f(EsField)}#23, does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#24 AS now_it_does#25]] \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/analysis.expected index 8dd19dd1a11b8..f0e2cc4908423 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2 AS employee_number#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{r}#24 AS now_it_does#25]] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2 AS employee_number#3, first_name{f(KeywordEsField)}#4, gender{f(KeywordEsField)}#5, height{f(EsField)}#6, height.float{f(EsField)}#7, height.half_float{f(EsField)}#8, height.scaled_float{f(EsField)}#9, hire_date{f(DateEsField)}#10, is_rehired{f(EsField)}#11, job_positions{f(KeywordEsField)}#12, languages{f(EsField)}#13, languages.byte{f(EsField)}#14, languages.long{f(EsField)}#15, languages.short{f(EsField)}#16, last_name{f(KeywordEsField)}#17, salary{f(EsField)}#18, salary_change{f(EsField)}#19, salary_change.int{f(EsField)}#20, salary_change.keyword{f(KeywordEsField)}#21, salary_change.long{f(EsField)}#22, still_hired{f(EsField)}#23, does_not_exist_field{r}#24 AS now_it_does#25]] \_Eval[[null[NULL] AS does_not_exist_field#24]] \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected index a802df25ed62b..c31cede9fea9b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] \_Eval[[TODOUBLE(does_not_exist{f}#0) + 1[INTEGER] AS x#1]] - \_Project[[avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4 AS employee_number#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#0]] + \_Project[[avg_worked_seconds{f(EsField)}#2, birth_date{f(DateEsField)}#3, emp_no{f(EsField)}#4 AS employee_number#5, first_name{f(KeywordEsField)}#6, gender{f(KeywordEsField)}#7, height{f(EsField)}#8, height.float{f(EsField)}#9, height.half_float{f(EsField)}#10, height.scaled_float{f(EsField)}#11, hire_date{f(DateEsField)}#12, is_rehired{f(EsField)}#13, job_positions{f(KeywordEsField)}#14, languages{f(EsField)}#15, languages.byte{f(EsField)}#16, languages.long{f(EsField)}#17, languages.short{f(EsField)}#18, last_name{f(KeywordEsField)}#19, salary{f(EsField)}#20, salary_change{f(EsField)}#21, salary_change.int{f(EsField)}#22, salary_change.keyword{f(KeywordEsField)}#23, salary_change.long{f(EsField)}#24, still_hired{f(EsField)}#25, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#0]] \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected index f96459400cd9a..1ead97977e5fb 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected @@ -1,5 +1,5 @@ Limit[1000[INTEGER],false,false] \_Eval[[TODOUBLE(does_not_exist{r}#0) + 1[INTEGER] AS x#1]] - \_Project[[avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4 AS employee_number#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{r}#0]] + \_Project[[avg_worked_seconds{f(EsField)}#2, birth_date{f(DateEsField)}#3, emp_no{f(EsField)}#4 AS employee_number#5, first_name{f(KeywordEsField)}#6, gender{f(KeywordEsField)}#7, height{f(EsField)}#8, height.float{f(EsField)}#9, height.half_float{f(EsField)}#10, height.scaled_float{f(EsField)}#11, hire_date{f(DateEsField)}#12, is_rehired{f(EsField)}#13, job_positions{f(KeywordEsField)}#14, languages{f(EsField)}#15, languages.byte{f(EsField)}#16, languages.long{f(EsField)}#17, languages.short{f(EsField)}#18, last_name{f(KeywordEsField)}#19, salary{f(EsField)}#20, salary_change{f(EsField)}#21, salary_change.int{f(EsField)}#22, salary_change.keyword{f(KeywordEsField)}#23, salary_change.long{f(EsField)}#24, still_hired{f(EsField)}#25, does_not_exist{r}#0]] \_Eval[[null[NULL] AS does_not_exist#0]] \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected index 0cc4d05a2041e..41a803dee2b34 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2 AS employee_number#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, neither_does_this{f}#24 AS now_it_does#25]] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2 AS employee_number#3, first_name{f(KeywordEsField)}#4, gender{f(KeywordEsField)}#5, height{f(EsField)}#6, height.float{f(EsField)}#7, height.half_float{f(EsField)}#8, height.scaled_float{f(EsField)}#9, hire_date{f(DateEsField)}#10, is_rehired{f(EsField)}#11, job_positions{f(KeywordEsField)}#12, languages{f(EsField)}#13, languages.byte{f(EsField)}#14, languages.long{f(EsField)}#15, languages.short{f(EsField)}#16, last_name{f(KeywordEsField)}#17, salary{f(EsField)}#18, salary_change{f(EsField)}#19, salary_change.int{f(EsField)}#20, salary_change.keyword{f(KeywordEsField)}#21, salary_change.long{f(EsField)}#22, still_hired{f(EsField)}#23, neither_does_this{f(PotentiallyUnmappedKeywordEsField)}#24 AS now_it_does#25]] \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#26, neither_does_this{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected index 7507e4ff3fa4e..f828b3f7c9f30 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2 AS employee_number#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, neither_does_this{r}#24 AS now_it_does#25]] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2 AS employee_number#3, first_name{f(KeywordEsField)}#4, gender{f(KeywordEsField)}#5, height{f(EsField)}#6, height.float{f(EsField)}#7, height.half_float{f(EsField)}#8, height.scaled_float{f(EsField)}#9, hire_date{f(DateEsField)}#10, is_rehired{f(EsField)}#11, job_positions{f(KeywordEsField)}#12, languages{f(EsField)}#13, languages.byte{f(EsField)}#14, languages.long{f(EsField)}#15, languages.short{f(EsField)}#16, last_name{f(KeywordEsField)}#17, salary{f(EsField)}#18, salary_change{f(EsField)}#19, salary_change.int{f(EsField)}#20, salary_change.keyword{f(KeywordEsField)}#21, salary_change.long{f(EsField)}#22, still_hired{f(EsField)}#23, neither_does_this{r}#24 AS now_it_does#25]] \_Eval[[null[NULL] AS does_not_exist_field#26, null[NULL] AS neither_does_this#24]] \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/analysis.expected index 441f28eeb2c20..fd2ab06e624be 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_OrderBy[[Order[does_not_exist{f}#0,ASC,LAST]]] +\_OrderBy[[Order[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#0,ASC,LAST]]] \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected index 663bca06a5e21..b6e10e3bc15c1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_OrderBy[[Order[TOLONG(does_not_exist1{f}#0) + 1[INTEGER],ASC,LAST], Order[does_not_exist2{f}#1,DESC,FIRST], Order[emp_no{f}#2,ASC,LAST]]] +\_OrderBy[[Order[TOLONG(does_not_exist1{f}#0) + 1[INTEGER],ASC,LAST], Order[does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#1,DESC,FIRST], Order[emp_no{f(EsField)}#2,ASC,LAST]]] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist1{f}#0, does_not_exist2{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected index f57ed4d6c6fda..272402c1c32eb 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_OrderBy[[Order[TOLONG(does_not_exist1{r}#0) + 1[INTEGER],ASC,LAST], Order[does_not_exist2{r}#1,DESC,FIRST], Order[emp_no{f}#2,ASC,LAST]]] +\_OrderBy[[Order[TOLONG(does_not_exist1{r}#0) + 1[INTEGER],ASC,LAST], Order[does_not_exist2{r}#1,DESC,FIRST], Order[emp_no{f(EsField)}#2,ASC,LAST]]] \_Eval[[null[NULL] AS does_not_exist1#0, null[NULL] AS does_not_exist2#1]] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected index 1b58079c3c0e9..72036927b0717 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[does_not_exist_field{f}#0],[does_not_exist_field{f}#0]] +\_Aggregate[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0],[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0]] \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected index 456247586e3be..4266a433ba529 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[],[COUNT(does_not_exist_field{f}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt#1]] +\_Aggregate[[],[COUNT(does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt#1]] \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected index 860ec580b8dd8..20e247409cc03 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[does_not_exist2{f}#0, emp_no{f}#1],[SUM(TODOUBLE(does_not_exist1{f}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{f}#0, emp_no{f}#1]] +\_Aggregate[[does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0, emp_no{f(EsField)}#1],[SUM(TODOUBLE(does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0, emp_no{f(EsField)}#1]] \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#1, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26, does_not_exist2{f}#0, does_not_exist1{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected index 3bd26f310af82..4e82f82142c41 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[does_not_exist2{r}#0, emp_no{f}#1],[SUM(TODOUBLE(does_not_exist1{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{r}#0, emp_no{f}#1]] +\_Aggregate[[does_not_exist2{r}#0, emp_no{f(EsField)}#1],[SUM(TODOUBLE(does_not_exist1{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{r}#0, emp_no{f(EsField)}#1]] \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist1#2]] \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#1, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected index a4fbd276de29c..de76cbb9a017a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{f}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER] OR TOLONG(does_not_exist2{f}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{f}#4)] AS c2#5]] +\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{f}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER] OR TOLONG(does_not_exist2{f}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{f(PotentiallyUnmappedKeywordEsField)}#4)] AS c2#5]] \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#1, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27, does_not_exist1{f}#0, does_not_exist2{f}#2, does_not_exist3{f}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected index 27b179dff2e21..3da6706296c63 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[does_not_exist2{f}#0],[SUM(TODOUBLE(does_not_exist1{f}#1),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#2, does_not_exist2{f}#0]] +\_Aggregate[[does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0],[SUM(TODOUBLE(does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#1),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#2, does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0]] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist2{f}#0, does_not_exist1{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected index 021eab43d5186..f8c89887de2f8 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[TODOUBLE(does_not_exist2{f}#0) + TODOUBLE(does_not_exist3{f}#1) AS s0#2, emp_no{f}#3 AS s1#4],[SUM(TODOUBLE(does_not_exist1{f}#5),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + s0{r}#2 + s1{r}#4 AS sum#6, s0{r}#2, s1{r}#4]] +\_Aggregate[[TODOUBLE(does_not_exist2{f}#0) + TODOUBLE(does_not_exist3{f}#1) AS s0#2, emp_no{f(EsField)}#3 AS s1#4],[SUM(TODOUBLE(does_not_exist1{f}#5),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + s0{r}#2 + s1{r}#4 AS sum#6, s0{r}#2, s1{r}#4]] \_EsRelation[employees][avg_worked_seconds{f}#7, birth_date{f}#8, emp_no{f}#3, first_name{f}#9, gender{f}#10, height{f}#11, height.float{f}#12, height.half_float{f}#13, height.scaled_float{f}#14, hire_date{f}#15, is_rehired{f}#16, job_positions{f}#17, languages{f}#18, languages.byte{f}#19, languages.long{f}#20, languages.short{f}#21, last_name{f}#22, salary{f}#23, salary_change{f}#24, salary_change.int{f}#25, salary_change.keyword{f}#26, salary_change.long{f}#27, still_hired{f}#28, does_not_exist2{f}#0, does_not_exist3{f}#1, does_not_exist1{f}#5, s0{f}#29] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected index a877b9d0f0588..f324c6cc494bb 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[TODOUBLE(does_not_exist2{r}#0) + TODOUBLE(does_not_exist3{r}#1) AS s0#2, emp_no{f}#3 AS s1#4],[SUM(TODOUBLE(does_not_exist1{r}#5),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + s0{r}#2 + s1{r}#4 AS sum#6, s0{r}#2, s1{r}#4]] +\_Aggregate[[TODOUBLE(does_not_exist2{r}#0) + TODOUBLE(does_not_exist3{r}#1) AS s0#2, emp_no{f(EsField)}#3 AS s1#4],[SUM(TODOUBLE(does_not_exist1{r}#5),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + s0{r}#2 + s1{r}#4 AS sum#6, s0{r}#2, s1{r}#4]] \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist3#1, null[NULL] AS does_not_exist1#5, null[NULL] AS s0#7]] \_EsRelation[employees][avg_worked_seconds{f}#8, birth_date{f}#9, emp_no{f}#3, first_name{f}#10, gender{f}#11, height{f}#12, height.float{f}#13, height.half_float{f}#14, height.scaled_float{f}#15, hire_date{f}#16, is_rehired{f}#17, job_positions{f}#18, languages{f}#19, languages.byte{f}#20, languages.long{f}#21, languages.short{f}#22, last_name{f}#23, salary{f}#24, salary_change{f}#25, salary_change.int{f}#26, salary_change.keyword{f}#27, salary_change.long{f}#28, still_hired{f}#29] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected index 2ad8609f9bac6..441d733d2e22d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[TODOUBLE(does_not_exist2{f}#0) AS d2#1, emp_no{f}#2],[SUM(TODOUBLE(does_not_exist1{f}#3),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + d2{r}#1 AS s#4, d2{r}#1, emp_no{f}#2]] +\_Aggregate[[TODOUBLE(does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0) AS d2#1, emp_no{f(EsField)}#2],[SUM(TODOUBLE(does_not_exist1{f}#3),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + d2{r}#1 AS s#4, d2{r}#1, emp_no{f(EsField)}#2]] \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#2, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26, does_not_exist2{f}#0, does_not_exist1{f}#3, d2{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected index f06e76b90283d..bcfbad0e4899c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[TODOUBLE(does_not_exist2{r}#0) AS d2#1, emp_no{f}#2],[SUM(TODOUBLE(does_not_exist1{r}#3),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + d2{r}#1 AS s#4, d2{r}#1, emp_no{f}#2]] +\_Aggregate[[TODOUBLE(does_not_exist2{r}#0) AS d2#1, emp_no{f(EsField)}#2],[SUM(TODOUBLE(does_not_exist1{r}#3),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + d2{r}#1 AS s#4, d2{r}#1, emp_no{f(EsField)}#2]] \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist1#3, null[NULL] AS d2#5]] \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#2, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected index d6b8d29c43430..5c3d84282236b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected @@ -1,11 +1,11 @@ Limit[1000[INTEGER],false,false] \_Project[[emp_no{r}#0, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] \_UnionAll[[avg_worked_seconds{r}#4, birth_date{r}#5, emp_no{r}#0, first_name{r}#6, gender{r}#7, height{r}#8, height.float{r}#9, height.half_float{r}#10, height.scaled_float{r}#11, hire_date{r}#12, is_rehired{r}#13, job_positions{r}#14, languages{r}#15, languages.byte{r}#16, languages.long{r}#17, languages.short{r}#18, last_name{r}#19, salary{r}#20, salary_change{r}#21, salary_change.int{r}#22, salary_change.keyword{r}#23, salary_change.long{r}#24, still_hired{r}#25, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] - |_Project[[avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48, language_code{r}#49, unmapped1{r}#50, unmapped2{r}#51]] + |_Project[[avg_worked_seconds{f(EsField)}#26, birth_date{f(DateEsField)}#27, emp_no{f(EsField)}#28, first_name{f(KeywordEsField)}#29, gender{f(KeywordEsField)}#30, height{f(EsField)}#31, height.float{f(EsField)}#32, height.half_float{f(EsField)}#33, height.scaled_float{f(EsField)}#34, hire_date{f(DateEsField)}#35, is_rehired{f(EsField)}#36, job_positions{f(KeywordEsField)}#37, languages{f(EsField)}#38, languages.byte{f(EsField)}#39, languages.long{f(EsField)}#40, languages.short{f(EsField)}#41, last_name{f(KeywordEsField)}#42, salary{f(EsField)}#43, salary_change{f(EsField)}#44, salary_change.int{f(EsField)}#45, salary_change.keyword{f(KeywordEsField)}#46, salary_change.long{f(EsField)}#47, still_hired{f(EsField)}#48, language_code{r}#49, unmapped1{r}#50, unmapped2{r}#51]] | \_Eval[[null[INTEGER] AS language_code#49, null[KEYWORD] AS unmapped1#50, null[KEYWORD] AS unmapped2#51]] | \_EsRelation[employees][avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48] - \_Project[[avg_worked_seconds{r}#52, birth_date{r}#53, emp_no{r}#54, first_name{r}#55, gender{r}#56, height{r}#57, height.float{r}#58, height.half_float{r}#59, height.scaled_float{r}#60, hire_date{r}#61, is_rehired{r}#62, job_positions{r}#63, languages{r}#64, languages.byte{r}#65, languages.long{r}#66, languages.short{r}#67, last_name{r}#68, salary{r}#69, salary_change{r}#70, salary_change.int{r}#71, salary_change.keyword{r}#72, salary_change.long{r}#73, still_hired{r}#74, language_code{f}#75, unmapped1{f}#76, unmapped2{f}#77]] + \_Project[[avg_worked_seconds{r}#52, birth_date{r}#53, emp_no{r}#54, first_name{r}#55, gender{r}#56, height{r}#57, height.float{r}#58, height.half_float{r}#59, height.scaled_float{r}#60, hire_date{r}#61, is_rehired{r}#62, job_positions{r}#63, languages{r}#64, languages.byte{r}#65, languages.long{r}#66, languages.short{r}#67, last_name{r}#68, salary{r}#69, salary_change{r}#70, salary_change.int{r}#71, salary_change.keyword{r}#72, salary_change.long{r}#73, still_hired{r}#74, language_code{f(EsField)}#75, unmapped1{f(PotentiallyUnmappedKeywordEsField)}#76, unmapped2{f(PotentiallyUnmappedKeywordEsField)}#77]] \_Eval[[null[LONG] AS avg_worked_seconds#52, null[DATETIME] AS birth_date#53, null[INTEGER] AS emp_no#54, null[KEYWORD] AS first_name#55, null[KEYWORD] AS gender#56, null[DOUBLE] AS height#57, null[DOUBLE] AS height.float#58, null[DOUBLE] AS height.half_float#59, null[DOUBLE] AS height.scaled_float#60, null[DATETIME] AS hire_date#61, null[BOOLEAN] AS is_rehired#62, null[KEYWORD] AS job_positions#63, null[INTEGER] AS languages#64, null[INTEGER] AS languages.byte#65, null[LONG] AS languages.long#66, null[INTEGER] AS languages.short#67, null[KEYWORD] AS last_name#68, null[INTEGER] AS salary#69, null[DOUBLE] AS salary_change#70, null[INTEGER] AS salary_change.int#71, null[KEYWORD] AS salary_change.keyword#72, null[LONG] AS salary_change.long#73, null[BOOLEAN] AS still_hired#74]] \_Subquery[] - \_Project[[language_code{f}#75, unmapped1{f}#76, unmapped2{f}#77]] + \_Project[[language_code{f(EsField)}#75, unmapped1{f(PotentiallyUnmappedKeywordEsField)}#76, unmapped2{f(PotentiallyUnmappedKeywordEsField)}#77]] \_EsRelation[languages][language_code{f}#75, language_name{f}#78, unmapped1{f}#76, unmapped2{f}#77] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/analysis.expected index 5edcc387fc727..12cb504aaa345 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/analysis.expected @@ -1,12 +1,12 @@ Limit[1000[INTEGER],false,false] \_Project[[emp_no{r}#0, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] \_UnionAll[[avg_worked_seconds{r}#4, birth_date{r}#5, emp_no{r}#0, first_name{r}#6, gender{r}#7, height{r}#8, height.float{r}#9, height.half_float{r}#10, height.scaled_float{r}#11, hire_date{r}#12, is_rehired{r}#13, job_positions{r}#14, languages{r}#15, languages.byte{r}#16, languages.long{r}#17, languages.short{r}#18, last_name{r}#19, salary{r}#20, salary_change{r}#21, salary_change.int{r}#22, salary_change.keyword{r}#23, salary_change.long{r}#24, still_hired{r}#25, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] - |_Project[[avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48, language_code{r}#49, unmapped1{r}#50, unmapped2{r}#51]] + |_Project[[avg_worked_seconds{f(EsField)}#26, birth_date{f(DateEsField)}#27, emp_no{f(EsField)}#28, first_name{f(KeywordEsField)}#29, gender{f(KeywordEsField)}#30, height{f(EsField)}#31, height.float{f(EsField)}#32, height.half_float{f(EsField)}#33, height.scaled_float{f(EsField)}#34, hire_date{f(DateEsField)}#35, is_rehired{f(EsField)}#36, job_positions{f(KeywordEsField)}#37, languages{f(EsField)}#38, languages.byte{f(EsField)}#39, languages.long{f(EsField)}#40, languages.short{f(EsField)}#41, last_name{f(KeywordEsField)}#42, salary{f(EsField)}#43, salary_change{f(EsField)}#44, salary_change.int{f(EsField)}#45, salary_change.keyword{f(KeywordEsField)}#46, salary_change.long{f(EsField)}#47, still_hired{f(EsField)}#48, language_code{r}#49, unmapped1{r}#50, unmapped2{r}#51]] | \_Eval[[null[INTEGER] AS language_code#49, null[NULL] AS unmapped1#50, null[NULL] AS unmapped2#51]] | \_EsRelation[employees][avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48] - \_Project[[avg_worked_seconds{r}#52, birth_date{r}#53, emp_no{r}#54, first_name{r}#55, gender{r}#56, height{r}#57, height.float{r}#58, height.half_float{r}#59, height.scaled_float{r}#60, hire_date{r}#61, is_rehired{r}#62, job_positions{r}#63, languages{r}#64, languages.byte{r}#65, languages.long{r}#66, languages.short{r}#67, last_name{r}#68, salary{r}#69, salary_change{r}#70, salary_change.int{r}#71, salary_change.keyword{r}#72, salary_change.long{r}#73, still_hired{r}#74, language_code{f}#75, unmapped1{r}#76, unmapped2{r}#77]] + \_Project[[avg_worked_seconds{r}#52, birth_date{r}#53, emp_no{r}#54, first_name{r}#55, gender{r}#56, height{r}#57, height.float{r}#58, height.half_float{r}#59, height.scaled_float{r}#60, hire_date{r}#61, is_rehired{r}#62, job_positions{r}#63, languages{r}#64, languages.byte{r}#65, languages.long{r}#66, languages.short{r}#67, last_name{r}#68, salary{r}#69, salary_change{r}#70, salary_change.int{r}#71, salary_change.keyword{r}#72, salary_change.long{r}#73, still_hired{r}#74, language_code{f(EsField)}#75, unmapped1{r}#76, unmapped2{r}#77]] \_Eval[[null[LONG] AS avg_worked_seconds#52, null[DATETIME] AS birth_date#53, null[INTEGER] AS emp_no#54, null[KEYWORD] AS first_name#55, null[KEYWORD] AS gender#56, null[DOUBLE] AS height#57, null[DOUBLE] AS height.float#58, null[DOUBLE] AS height.half_float#59, null[DOUBLE] AS height.scaled_float#60, null[DATETIME] AS hire_date#61, null[BOOLEAN] AS is_rehired#62, null[KEYWORD] AS job_positions#63, null[INTEGER] AS languages#64, null[INTEGER] AS languages.byte#65, null[LONG] AS languages.long#66, null[INTEGER] AS languages.short#67, null[KEYWORD] AS last_name#68, null[INTEGER] AS salary#69, null[DOUBLE] AS salary_change#70, null[INTEGER] AS salary_change.int#71, null[KEYWORD] AS salary_change.keyword#72, null[LONG] AS salary_change.long#73, null[BOOLEAN] AS still_hired#74]] \_Subquery[] - \_Project[[language_code{f}#75, unmapped1{r}#76, unmapped2{r}#77]] + \_Project[[language_code{f(EsField)}#75, unmapped1{r}#76, unmapped2{r}#77]] \_Eval[[null[NULL] AS unmapped1#76, null[NULL] AS unmapped2#77]] \_EsRelation[languages][language_code{f}#75, language_name{f}#78] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected index 0f0fb589b8c87..b4452dd003c30 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected @@ -1,11 +1,11 @@ Limit[1000[INTEGER],false,false] \_Project[[emp_no{r}#0, language_code{r}#1, does_not_exist{r}#2]] \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, language_code{r}#1, does_not_exist{r}#2]] - |_Project[[avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, language_code{r}#48, does_not_exist{r}#49]] + |_Project[[avg_worked_seconds{f(EsField)}#25, birth_date{f(DateEsField)}#26, emp_no{f(EsField)}#27, first_name{f(KeywordEsField)}#28, gender{f(KeywordEsField)}#29, height{f(EsField)}#30, height.float{f(EsField)}#31, height.half_float{f(EsField)}#32, height.scaled_float{f(EsField)}#33, hire_date{f(DateEsField)}#34, is_rehired{f(EsField)}#35, job_positions{f(KeywordEsField)}#36, languages{f(EsField)}#37, languages.byte{f(EsField)}#38, languages.long{f(EsField)}#39, languages.short{f(EsField)}#40, last_name{f(KeywordEsField)}#41, salary{f(EsField)}#42, salary_change{f(EsField)}#43, salary_change.int{f(EsField)}#44, salary_change.keyword{f(KeywordEsField)}#45, salary_change.long{f(EsField)}#46, still_hired{f(EsField)}#47, language_code{r}#48, does_not_exist{r}#49]] | \_Eval[[null[INTEGER] AS language_code#48, null[KEYWORD] AS does_not_exist#49]] | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] - \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f}#73, does_not_exist{f}#74]] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f(EsField)}#73, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74]] \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] \_Subquery[] - \_Project[[language_code{f}#73, does_not_exist{f}#74]] + \_Project[[language_code{f(EsField)}#73, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74]] \_EsRelation[languages][language_code{f}#73, language_name{f}#75, does_not_exist{f}#74] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected index 37e20fe2c90c4..6efd06cbbc7de 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected @@ -1,12 +1,12 @@ Limit[1000[INTEGER],false,false] \_Project[[emp_no{r}#0, language_code{r}#1, does_not_exist{r}#2]] \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, language_code{r}#1, does_not_exist{r}#2]] - |_Project[[avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, language_code{r}#48, does_not_exist{r}#49]] + |_Project[[avg_worked_seconds{f(EsField)}#25, birth_date{f(DateEsField)}#26, emp_no{f(EsField)}#27, first_name{f(KeywordEsField)}#28, gender{f(KeywordEsField)}#29, height{f(EsField)}#30, height.float{f(EsField)}#31, height.half_float{f(EsField)}#32, height.scaled_float{f(EsField)}#33, hire_date{f(DateEsField)}#34, is_rehired{f(EsField)}#35, job_positions{f(KeywordEsField)}#36, languages{f(EsField)}#37, languages.byte{f(EsField)}#38, languages.long{f(EsField)}#39, languages.short{f(EsField)}#40, last_name{f(KeywordEsField)}#41, salary{f(EsField)}#42, salary_change{f(EsField)}#43, salary_change.int{f(EsField)}#44, salary_change.keyword{f(KeywordEsField)}#45, salary_change.long{f(EsField)}#46, still_hired{f(EsField)}#47, language_code{r}#48, does_not_exist{r}#49]] | \_Eval[[null[INTEGER] AS language_code#48, null[NULL] AS does_not_exist#49]] | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] - \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f}#73, does_not_exist{r}#74]] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f(EsField)}#73, does_not_exist{r}#74]] \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] \_Subquery[] - \_Project[[language_code{f}#73, does_not_exist{r}#74]] + \_Project[[language_code{f(EsField)}#73, does_not_exist{r}#74]] \_Eval[[null[NULL] AS does_not_exist#74]] \_EsRelation[languages][language_code{f}#73, language_name{f}#75] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected index 48317bbb23980..d7d41100c00dc 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected @@ -1,11 +1,11 @@ Limit[1000[INTEGER],false,false] \_Project[[emp_no{r}#0, max_ts{r}#1, does_not_exist{r}#2]] \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, max_ts{r}#1, does_not_exist{r}#2]] - |_Project[[avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, max_ts{r}#48, does_not_exist{r}#49]] + |_Project[[avg_worked_seconds{f(EsField)}#25, birth_date{f(DateEsField)}#26, emp_no{f(EsField)}#27, first_name{f(KeywordEsField)}#28, gender{f(KeywordEsField)}#29, height{f(EsField)}#30, height.float{f(EsField)}#31, height.half_float{f(EsField)}#32, height.scaled_float{f(EsField)}#33, hire_date{f(DateEsField)}#34, is_rehired{f(EsField)}#35, job_positions{f(KeywordEsField)}#36, languages{f(EsField)}#37, languages.byte{f(EsField)}#38, languages.long{f(EsField)}#39, languages.short{f(EsField)}#40, last_name{f(KeywordEsField)}#41, salary{f(EsField)}#42, salary_change{f(EsField)}#43, salary_change.int{f(EsField)}#44, salary_change.keyword{f(KeywordEsField)}#45, salary_change.long{f(EsField)}#46, still_hired{f(EsField)}#47, max_ts{r}#48, does_not_exist{r}#49]] | \_Eval[[null[DATETIME] AS max_ts#48, null[KEYWORD] AS does_not_exist#49]] | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] - \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, max_ts{r}#73, does_not_exist{f}#74]] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, max_ts{r}#73, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74]] \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] \_Subquery[] - \_Aggregate[[does_not_exist{f}#74],[MAX(@timestamp{f}#75,true[BOOLEAN],PT0S[TIME_DURATION]) AS max_ts#73, does_not_exist{f}#74]] + \_Aggregate[[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74],[MAX(@timestamp{f(DateEsField)}#75,true[BOOLEAN],PT0S[TIME_DURATION]) AS max_ts#73, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74]] \_EsRelation[sample_data][@timestamp{f}#75, client_ip{f}#76, event_duration{f}#77, message{f}#78, does_not_exist{f}#74] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/analysis.expected index 1def35de13537..45949bb3dc895 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/analysis.expected @@ -1,12 +1,12 @@ Limit[1000[INTEGER],false,false] \_Project[[emp_no{r}#0, max_ts{r}#1, does_not_exist{r}#2]] \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, max_ts{r}#1, does_not_exist{r}#2]] - |_Project[[avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, max_ts{r}#48, does_not_exist{r}#49]] + |_Project[[avg_worked_seconds{f(EsField)}#25, birth_date{f(DateEsField)}#26, emp_no{f(EsField)}#27, first_name{f(KeywordEsField)}#28, gender{f(KeywordEsField)}#29, height{f(EsField)}#30, height.float{f(EsField)}#31, height.half_float{f(EsField)}#32, height.scaled_float{f(EsField)}#33, hire_date{f(DateEsField)}#34, is_rehired{f(EsField)}#35, job_positions{f(KeywordEsField)}#36, languages{f(EsField)}#37, languages.byte{f(EsField)}#38, languages.long{f(EsField)}#39, languages.short{f(EsField)}#40, last_name{f(KeywordEsField)}#41, salary{f(EsField)}#42, salary_change{f(EsField)}#43, salary_change.int{f(EsField)}#44, salary_change.keyword{f(KeywordEsField)}#45, salary_change.long{f(EsField)}#46, still_hired{f(EsField)}#47, max_ts{r}#48, does_not_exist{r}#49]] | \_Eval[[null[DATETIME] AS max_ts#48, null[NULL] AS does_not_exist#49]] | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, max_ts{r}#73, does_not_exist{r}#74]] \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] \_Subquery[] - \_Aggregate[[does_not_exist{r}#74],[MAX(@timestamp{f}#75,true[BOOLEAN],PT0S[TIME_DURATION]) AS max_ts#73, does_not_exist{r}#74]] + \_Aggregate[[does_not_exist{r}#74],[MAX(@timestamp{f(DateEsField)}#75,true[BOOLEAN],PT0S[TIME_DURATION]) AS max_ts#73, does_not_exist{r}#74]] \_Eval[[null[NULL] AS does_not_exist#74]] \_EsRelation[sample_data][@timestamp{f}#75, client_ip{f}#76, event_duration{f}#77, message{f}#78] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/analysis.expected index 5dc208a9d01de..370b360a7f332 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[TBUCKET(P1D[DATE_PERIOD],@timestamp{f}#0) AS tbucket(1 day)#1],[SUM(TODOUBLE(does_not_exist{f}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, tbucket(1 day){r}#1]] +\_Aggregate[[TBUCKET(P1D[DATE_PERIOD],@timestamp{f(DateEsField)}#0) AS tbucket(1 day)#1],[SUM(TODOUBLE(does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, tbucket(1 day){r}#1]] \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#5, event_duration{f}#6, message{f}#7, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/analysis.expected index 630cfad99e1d9..a606b9204678f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[TBUCKET(P1D[DATE_PERIOD],@timestamp{f}#0) AS tbucket(1 day)#1],[SUM(TODOUBLE(does_not_exist{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, tbucket(1 day){r}#1]] +\_Aggregate[[TBUCKET(P1D[DATE_PERIOD],@timestamp{f(DateEsField)}#0) AS tbucket(1 day)#1],[SUM(TODOUBLE(does_not_exist{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, tbucket(1 day){r}#1]] \_Eval[[null[NULL] AS does_not_exist#2]] \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#5, event_duration{f}#6, message{f}#7] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/analysis.expected index 0a5930587890d..50bd7d1993840 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#0) AS tbucket(1 hour)#1, does_not_exist{f}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#3, tbucket(1 hour){r}#1, does_not_exist{f}#2]] +\_Aggregate[[TBUCKET(PT1H[TIME_DURATION],@timestamp{f(DateEsField)}#0) AS tbucket(1 hour)#1, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#3, tbucket(1 hour){r}#1, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2]] \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/analysis.expected index 0ddcf7afa969d..fa9425fdce85b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Aggregate[[TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#0) AS tbucket(1 hour)#1, does_not_exist{r}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#3, tbucket(1 hour){r}#1, does_not_exist{r}#2]] +\_Aggregate[[TBUCKET(PT1H[TIME_DURATION],@timestamp{f(DateEsField)}#0) AS tbucket(1 hour)#1, does_not_exist{r}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#3, tbucket(1 hour){r}#1, does_not_exist{r}#2]] \_Eval[[null[NULL] AS does_not_exist#2]] \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/analysis.expected index a53ba9b57e55d..71e224132f7cd 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/analysis.expected @@ -1,3 +1,3 @@ Limit[1000000[INTEGER],false,false] -\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(FIRSTOVERTIME(TODOUBLE(does_not_exist{f}#3),true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS f#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] +\_TimeSeriesAggregate[[_timeseries{f(EsField)}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f(DateEsField)}#1) AS tbucket(1 hour)#2],[VALUES(FIRSTOVERTIME(TODOUBLE(does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#3),true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f(DateEsField)}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS f#4, tbucket(1 hour){r}#2],null,@timestamp{f(DateEsField)}#1] \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#5, cluster{f}#6, event{f}#7, event_city{f}#8, event_city_boundary{f}#9, event_location{f}#10, event_log{f}#11, event_shape{f}#12, events_received{f}#13, network.bytes_in{f}#14, network.cost{f}#15, network.eth0.currently_connected_clients{f}#16, network.eth0.firmware_version{f}#17, network.eth0.last_up{f}#18, network.eth0.rx{f}#19, network.eth0.tx{f}#20, network.eth0.up{f}#21, network.total_bytes_in{f}#22, network.total_bytes_out{f}#23, network.total_cost{f}#24, pod{f}#25, region{f}#26, _timeseries{f}#0, does_not_exist{f}#3] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/analysis.expected index f5b122a261793..98c91207aa550 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000000[INTEGER],false,false] -\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(FIRSTOVERTIME(TODOUBLE(does_not_exist{r}#3),true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS f#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] +\_TimeSeriesAggregate[[_timeseries{f(EsField)}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f(DateEsField)}#1) AS tbucket(1 hour)#2],[VALUES(FIRSTOVERTIME(TODOUBLE(does_not_exist{r}#3),true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f(DateEsField)}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS f#4, tbucket(1 hour){r}#2],null,@timestamp{f(DateEsField)}#1] \_Eval[[null[NULL] AS does_not_exist#3]] \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#5, cluster{f}#6, event{f}#7, event_city{f}#8, event_city_boundary{f}#9, event_location{f}#10, event_log{f}#11, event_shape{f}#12, events_received{f}#13, network.bytes_in{f}#14, network.cost{f}#15, network.eth0.currently_connected_clients{f}#16, network.eth0.firmware_version{f}#17, network.eth0.last_up{f}#18, network.eth0.rx{f}#19, network.eth0.tx{f}#20, network.eth0.up{f}#21, network.total_bytes_in{f}#22, network.total_bytes_out{f}#23, network.total_cost{f}#24, pod{f}#25, region{f}#26, _timeseries{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/analysis.expected index 41c760dcac978..359c8bd55b39d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/analysis.expected @@ -1,4 +1,4 @@ Limit[1000000[INTEGER],false,false] -\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(RATE(does_not_exist{r}#3,true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS r#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] +\_TimeSeriesAggregate[[_timeseries{f(EsField)}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f(DateEsField)}#1) AS tbucket(1 hour)#2],[VALUES(RATE(does_not_exist{r}#3,true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f(DateEsField)}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS r#4, tbucket(1 hour){r}#2],null,@timestamp{f(DateEsField)}#1] \_Eval[[null[NULL] AS does_not_exist#3]] \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#5, cluster{f}#6, event{f}#7, event_city{f}#8, event_city_boundary{f}#9, event_location{f}#10, event_log{f}#11, event_shape{f}#12, events_received{f}#13, network.bytes_in{f}#14, network.cost{f}#15, network.eth0.currently_connected_clients{f}#16, network.eth0.firmware_version{f}#17, network.eth0.last_up{f}#18, network.eth0.rx{f}#19, network.eth0.tx{f}#20, network.eth0.up{f}#21, network.total_bytes_in{f}#22, network.total_bytes_out{f}#23, network.total_cost{f}#24, pod{f}#25, region{f}#26, _timeseries{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected index 504e54c3064ee..e8673db3d1c8d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected @@ -2,10 +2,10 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],SINGLE,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_EvalExec[[BUCKET(date{r}#4,P1D[DATE_PERIOD]) AS x#0]] \_MergeExec[[date{r}#4]] - |_ProjectExec[[date{f}#5]] + |_ProjectExec[[date{f(DateEsField)}#5]] | \_LimitExec[1000[INTEGER],null] - | \_ExchangeExec[[date{f}#5],false] - | \_ProjectExec[[date{f}#5]] + | \_ExchangeExec[[date{f(DateEsField)}#5],false] + | \_ProjectExec[[date{f(DateEsField)}#5]] | \_FieldExtractExec[date{f}#5]<[],[]> | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#6], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { @@ -21,10 +21,10 @@ LimitExec[1000[INTEGER],null] "source" : "integer > 100@2:15" } }, tags=[]]]] - \_ProjectExec[[date{f}#7]] + \_ProjectExec[[date{f(DateEsField)}#7]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[date{f}#7],false] - \_ProjectExec[[date{f}#7]] + \_ExchangeExec[[date{f(DateEsField)}#7],false] + \_ProjectExec[[date{f(DateEsField)}#7]] \_FieldExtractExec[date{f}#7]<[],[]> \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "match" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected index 72dbdcc974f68..5375b59ec8cef 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected @@ -2,10 +2,10 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],SINGLE,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_EvalExec[[DATETRUNC(P1D[DATE_PERIOD],date{r}#4) AS x#0]] \_MergeExec[[date{r}#4]] - |_ProjectExec[[date{f}#5]] + |_ProjectExec[[date{f(DateEsField)}#5]] | \_LimitExec[1000[INTEGER],null] - | \_ExchangeExec[[date{f}#5],false] - | \_ProjectExec[[date{f}#5]] + | \_ExchangeExec[[date{f(DateEsField)}#5],false] + | \_ProjectExec[[date{f(DateEsField)}#5]] | \_FieldExtractExec[date{f}#5]<[],[]> | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#6], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { @@ -21,10 +21,10 @@ LimitExec[1000[INTEGER],null] "source" : "integer > 100@2:15" } }, tags=[]]]] - \_ProjectExec[[date{f}#7]] + \_ProjectExec[[date{f(DateEsField)}#7]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[date{f}#7],false] - \_ProjectExec[[date{f}#7]] + \_ExchangeExec[[date{f(DateEsField)}#7],false] + \_ProjectExec[[date{f(DateEsField)}#7]] \_FieldExtractExec[date{f}#7]<[],[]> \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "match" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected index 5c5cb8da952c2..0ba82653fa90c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected @@ -2,10 +2,10 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],SINGLE,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_EvalExec[[ROUNDTO(date{r}#4,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] \_MergeExec[[date{r}#4]] - |_ProjectExec[[date{f}#5]] + |_ProjectExec[[date{f(DateEsField)}#5]] | \_LimitExec[1000[INTEGER],null] - | \_ExchangeExec[[date{f}#5],false] - | \_ProjectExec[[date{f}#5]] + | \_ExchangeExec[[date{f(DateEsField)}#5],false] + | \_ProjectExec[[date{f(DateEsField)}#5]] | \_FieldExtractExec[date{f}#5]<[],[]> | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#6], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { @@ -21,10 +21,10 @@ LimitExec[1000[INTEGER],null] "source" : "integer > 100@2:15" } }, tags=[]]]] - \_ProjectExec[[date{f}#7]] + \_ProjectExec[[date{f(DateEsField)}#7]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[date{f}#7],false] - \_ProjectExec[[date{f}#7]] + \_ExchangeExec[[date{f(DateEsField)}#7],false] + \_ProjectExec[[date{f(DateEsField)}#7]] \_FieldExtractExec[date{f}#7]<[],[]> \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "match" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected index 37d5c04ccc89b..48ca6656e3cd0 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected @@ -2,9 +2,9 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[ROUNDTO(date{f}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] + \_EvalExec[[ROUNDTO(date{f(DateEsField)}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] \_FieldExtractExec[date{f}#6]<[],[]> - \_LookupJoinExec[[integer{f}#7],[language_code{f}#8],[],null] + \_LookupJoinExec[[integer{f(EsField)}#7],[language_code{f(EsField)}#8],[],null] |_FieldExtractExec[integer{f}#7]<[],[]> | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#9], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected index 37d5c04ccc89b..48ca6656e3cd0 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected @@ -2,9 +2,9 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[ROUNDTO(date{f}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] + \_EvalExec[[ROUNDTO(date{f(DateEsField)}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] \_FieldExtractExec[date{f}#6]<[],[]> - \_LookupJoinExec[[integer{f}#7],[language_code{f}#8],[],null] + \_LookupJoinExec[[integer{f(EsField)}#7],[language_code{f(EsField)}#8],[],null] |_FieldExtractExec[integer{f}#7]<[],[]> | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#9], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected index 37d5c04ccc89b..48ca6656e3cd0 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected @@ -2,9 +2,9 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[ROUNDTO(date{f}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] + \_EvalExec[[ROUNDTO(date{f(DateEsField)}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] \_FieldExtractExec[date{f}#6]<[],[]> - \_LookupJoinExec[[integer{f}#7],[language_code{f}#8],[],null] + \_LookupJoinExec[[integer{f(EsField)}#7],[language_code{f(EsField)}#8],[],null] |_FieldExtractExec[integer{f}#7]<[],[]> | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#9], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected index 9bed443f7dbca..4b49127073688 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] +\_AggregateExec[[x{r}#0],[SUM(long{f(EsField)}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] \_ExchangeExec[[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],true] - \_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] + \_AggregateExec[[x{r}#0],[SUM(long{f(EsField)}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] \_FieldExtractExec[long{f}#1]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f}#12 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#12 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#13, $$date$round_to$datetime{f}#12], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected index 8a37befcc7c7e..bc224463f20da 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] +\_AggregateExec[[x{r}#0],[SUM(long{f(EsField)}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] \_ExchangeExec[[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],true] - \_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] + \_AggregateExec[[x{r}#0],[SUM(long{f(EsField)}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] \_FieldExtractExec[long{f}#1]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f}#12 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#12 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#13, $$date$round_to$datetime{f}#12], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected index dd6350bd70a36..45bd1357a9060 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] +\_AggregateExec[[x{r}#0],[SUM(long{f(EsField)}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] \_ExchangeExec[[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],true] - \_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] + \_AggregateExec[[x{r}#0],[SUM(long{f(EsField)}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] \_FieldExtractExec[long{f}#1]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f}#12 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#12 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#13, $$date$round_to$datetime{f}#12], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected index 8b039c4db5c27..9e5e8117ad64c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected @@ -2,7 +2,7 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#6 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected index 1783e8bca9fb9..1844a19d493e8 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected @@ -2,7 +2,7 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#6 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected index 741c5cc853d00..e4c62c4a8e048 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected @@ -2,7 +2,7 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#6 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected index ba745f8603cf2..06e902b264e67 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected @@ -2,7 +2,7 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#6 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected index 3bb91af178169..7ee987d4dd704 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected @@ -2,7 +2,7 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#6 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected index 0adf9b4716949..717191ed291d6 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected @@ -2,7 +2,7 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#6 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected index 54ec4005471fb..4b9a4f78f2b83 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected @@ -3,7 +3,7 @@ LimitExec[1000[INTEGER],null] \_ExchangeExec[[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],INITIAL,[x{r}#0, $$count(*) where long > 10$count{r}#5, $$count(*) where long > 10$seen{r}#6],16] \_FieldExtractExec[long{f}#1]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f}#7 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#7 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8, $$date$round_to$datetime{f}#7], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected index 8665d69bc4af1..fad943e8cfcc5 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected @@ -3,7 +3,7 @@ LimitExec[1000[INTEGER],null] \_ExchangeExec[[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],INITIAL,[x{r}#0, $$count(*) where long > 10$count{r}#5, $$count(*) where long > 10$seen{r}#6],16] \_FieldExtractExec[long{f}#1]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f}#7 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#7 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8, $$date$round_to$datetime{f}#7], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected index d59fd1a30f5dc..266ce4e2b05d7 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected @@ -3,7 +3,7 @@ LimitExec[1000[INTEGER],null] \_ExchangeExec[[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],INITIAL,[x{r}#0, $$count(*) where long > 10$count{r}#5, $$count(*) where long > 10$seen{r}#6],16] \_FieldExtractExec[long{f}#1]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f}#7 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#7 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8, $$date$round_to$datetime{f}#7], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected index f4aec5a235e42..930a27274aec3 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] -\_TopNExec[[Order[date{f}#0,ASC,LAST]],5[INTEGER],null] - \_ExchangeExec[[!alias_integer, date{f}#0, x{r}#1],false] - \_ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] +ProjectExec[[!alias_integer, date{f(DateEsField)}#0, x{r}#1]] +\_TopNExec[[Order[date{f(DateEsField)}#0,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[!alias_integer, date{f(DateEsField)}#0, x{r}#1],false] + \_ProjectExec[[!alias_integer, date{f(DateEsField)}#0, x{r}#1]] \_FieldExtractExec[!alias_integer]<[],[]> - \_EvalExec[[ROUNDTO(date{f}#0,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#1]] + \_EvalExec[[ROUNDTO(date{f(DateEsField)}#0,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#1]] \_FieldExtractExec[date{f}#0]<[],[]> \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#2], limit[5], sort[[FieldSort[field=date{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[1056] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected index f4aec5a235e42..930a27274aec3 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] -\_TopNExec[[Order[date{f}#0,ASC,LAST]],5[INTEGER],null] - \_ExchangeExec[[!alias_integer, date{f}#0, x{r}#1],false] - \_ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] +ProjectExec[[!alias_integer, date{f(DateEsField)}#0, x{r}#1]] +\_TopNExec[[Order[date{f(DateEsField)}#0,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[!alias_integer, date{f(DateEsField)}#0, x{r}#1],false] + \_ProjectExec[[!alias_integer, date{f(DateEsField)}#0, x{r}#1]] \_FieldExtractExec[!alias_integer]<[],[]> - \_EvalExec[[ROUNDTO(date{f}#0,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#1]] + \_EvalExec[[ROUNDTO(date{f(DateEsField)}#0,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#1]] \_FieldExtractExec[date{f}#0]<[],[]> \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#2], limit[5], sort[[FieldSort[field=date{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[1056] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected index d6af15a5d5b6f..ef73b853c3e12 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected @@ -3,11 +3,11 @@ LimitExec[1000[INTEGER],null] |_ProjectExec[[x{r}#4, y{r}#5, hd{r}#6, _fork{r}#7]] | \_EvalExec[[fork1[KEYWORD] AS _fork#7]] | \_LimitExec[1000[INTEGER],null] - | \_AggregateExec[[hd{r}#6],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#4, MAX(long{f}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#5, hd{r}#6],FINAL,[hd{r}#6, $$x$count{r}#9, $$x$seen{r}#10, $$y$max{r}#11, $$y$seen{r}#12],null] + | \_AggregateExec[[hd{r}#6],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#4, MAX(long{f(EsField)}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#5, hd{r}#6],FINAL,[hd{r}#6, $$x$count{r}#9, $$x$seen{r}#10, $$y$max{r}#11, $$y$seen{r}#12],null] | \_ExchangeExec[[hd{r}#6, $$x$count{r}#9, $$x$seen{r}#10, $$y$max{r}#11, $$y$seen{r}#12],true] - | \_AggregateExec[[hd{r}#6],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#4, MAX(long{f}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#5, hd{r}#6],INITIAL,[hd{r}#6, $$x$count{r}#13, $$x$seen{r}#14, $$y$max{r}#15, $$y$seen{r}#16],24] + | \_AggregateExec[[hd{r}#6],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#4, MAX(long{f(EsField)}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#5, hd{r}#6],INITIAL,[hd{r}#6, $$x$count{r}#13, $$x$seen{r}#14, $$y$max{r}#15, $$y$seen{r}#16],24] | \_FieldExtractExec[long{f}#8]<[],[]> - | \_EvalExec[[$$date$round_to$datetime{f}#17 AS hd#6]] + | \_EvalExec[[$$date$round_to$datetime{f(EsField)}#17 AS hd#6]] | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#18, $$date$round_to$datetime{f}#17], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -86,10 +86,10 @@ LimitExec[1000[INTEGER],null] \_ProjectExec[[x{r}#19, y{r}#20, hd{r}#21, _fork{r}#7]] \_EvalExec[[fork2[KEYWORD] AS _fork#7]] \_LimitExec[1000[INTEGER],null] - \_AggregateExec[[hd{r}#21],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#19, MIN(long{f}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#20, hd{r}#21],FINAL,[hd{r}#21, $$x$count{r}#23, $$x$seen{r}#24, $$y$min{r}#25, $$y$seen{r}#26],null] + \_AggregateExec[[hd{r}#21],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#19, MIN(long{f(EsField)}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#20, hd{r}#21],FINAL,[hd{r}#21, $$x$count{r}#23, $$x$seen{r}#24, $$y$min{r}#25, $$y$seen{r}#26],null] \_ExchangeExec[[hd{r}#21, $$x$count{r}#23, $$x$seen{r}#24, $$y$min{r}#25, $$y$seen{r}#26],true] - \_AggregateExec[[hd{r}#21],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#19, MIN(long{f}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#20, hd{r}#21],INITIAL,[hd{r}#21, $$x$count{r}#27, $$x$seen{r}#28, $$y$min{r}#29, $$y$seen{r}#30],24] + \_AggregateExec[[hd{r}#21],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#19, MIN(long{f(EsField)}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#20, hd{r}#21],INITIAL,[hd{r}#21, $$x$count{r}#27, $$x$seen{r}#28, $$y$min{r}#29, $$y$seen{r}#30],24] \_FieldExtractExec[long{f}#22]<[],[]> - \_EvalExec[[DATETRUNC(P2D[DATE_PERIOD],date{f}#31) AS hd#21]] + \_EvalExec[[DATETRUNC(P2D[DATE_PERIOD],date{f(DateEsField)}#31) AS hd#21]] \_FieldExtractExec[date{f}#31]<[],[]> \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#32], limit[], sort[] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected index 9f3fe63e4a21f..97b2db7cb91bf 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected @@ -1,8 +1,8 @@ ProjectExec[[x{r}#0, cnt{r}#1, date{r}#2]] \_LimitExec[1000[INTEGER],null] \_MergeExec[[alias_integer{r}#3, boolean{r}#4, byte{r}#5, constant_keyword-foo{r}#6, date{r}#2, date_nanos{r}#7, dense_vector{r}#8, double{r}#9, float{r}#10, half_float{r}#11, integer{r}#12, ip{r}#13, keyword{r}#14, long{r}#15, scaled_float{r}#16, semantic_text{r}#17, short{r}#18, text{r}#19, unsigned_long{r}#20, version{r}#21, wildcard{r}#22, cnt{r}#1, x{r}#0]] - |_ExchangeExec[[alias_integer{r}#23, boolean{f}#24, byte{f}#25, constant_keyword-foo{f}#26, date{f}#27, date_nanos{f}#28, dense_vector{f}#29, double{f}#30, float{f}#31, half_float{f}#32, integer{f}#33, ip{f}#34, keyword{f}#35, long{f}#36, scaled_float{f}#37, semantic_text{f}#38, short{f}#39, text{f}#40, unsigned_long{f}#41, version{f}#42, wildcard{f}#43, cnt{r}#44, x{r}#45],false] - | \_ProjectExec[[alias_integer{r}#23, boolean{f}#24, byte{f}#25, constant_keyword-foo{f}#26, date{f}#27, date_nanos{f}#28, dense_vector{f}#29, double{f}#30, float{f}#31, half_float{f}#32, integer{f}#33, ip{f}#34, keyword{f}#35, long{f}#36, scaled_float{f}#37, semantic_text{f}#38, short{f}#39, text{f}#40, unsigned_long{f}#41, version{f}#42, wildcard{f}#43, cnt{r}#44, x{r}#45]] + |_ExchangeExec[[alias_integer{r}#23, boolean{f(EsField)}#24, byte{f(EsField)}#25, constant_keyword-foo{f(KeywordEsField)}#26, date{f(DateEsField)}#27, date_nanos{f(EsField)}#28, dense_vector{f(EsField)}#29, double{f(EsField)}#30, float{f(EsField)}#31, half_float{f(EsField)}#32, integer{f(EsField)}#33, ip{f(EsField)}#34, keyword{f(KeywordEsField)}#35, long{f(EsField)}#36, scaled_float{f(EsField)}#37, semantic_text{f(TextEsField)}#38, short{f(EsField)}#39, text{f(TextEsField)}#40, unsigned_long{f(EsField)}#41, version{f(EsField)}#42, wildcard{f(KeywordEsField)}#43, cnt{r}#44, x{r}#45],false] + | \_ProjectExec[[alias_integer{r}#23, boolean{f(EsField)}#24, byte{f(EsField)}#25, constant_keyword-foo{f(KeywordEsField)}#26, date{f(DateEsField)}#27, date_nanos{f(EsField)}#28, dense_vector{f(EsField)}#29, double{f(EsField)}#30, float{f(EsField)}#31, half_float{f(EsField)}#32, integer{f(EsField)}#33, ip{f(EsField)}#34, keyword{f(KeywordEsField)}#35, long{f(EsField)}#36, scaled_float{f(EsField)}#37, semantic_text{f(TextEsField)}#38, short{f(EsField)}#39, text{f(TextEsField)}#40, unsigned_long{f(EsField)}#41, version{f(EsField)}#42, wildcard{f(KeywordEsField)}#43, cnt{r}#44, x{r}#45]] | \_FieldExtractExec[boolean{f}#24, byte{f}#25, constant_keyword-foo{f}#26, date{f}#27, date_nanos{f}#28, dense_vector{f}#29, double{f}#30, float{f}#31, half_float{f}#32, integer{f}#33, ip{f}#34, keyword{f}#35, long{f}#36, scaled_float{f}#37, semantic_text{f}#38, short{f}#39, text{f}#40, unsigned_long{f}#41, version{f}#42, wildcard{f}#43]<[],[]> | \_EvalExec[[null[LONG] AS cnt#44, null[DATETIME] AS x#45, null[KEYWORD] AS alias_integer#23]] | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#46], limit[], sort[] estimatedRowSize[6472] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected index 71c01677f83a5..535953e39d9cf 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[_doc{f}#3, hire_date{f}#1]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] +\_ProjectExec[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#1]] \_FieldExtractExec[hire_date{f}#1]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected index fc4d011c9a8fb..6b9bd659d3727 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#3, hire_date{f}#1]] -\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] +Project[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected index 4b4fc0c891ac1..b4351eb176c15 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] +\_ProjectExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2]] \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> - \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file + \_TopNExec[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected index 84b502cae4e25..fac7b0beb280e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] -\_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] +ProjectExec[[hire_date{f(DateEsField)}#0, salary{f(EsField)}#1, emp_no{f(EsField)}#2]] +\_TopNExec[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] -\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] +Project[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected index 8f49d89b830ce..bb3e478910242 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[hire_date{f}#0, $$order_by$0{r}#1],false] -\_ProjectExec[[_doc{f}#2, $$order_by$0{r}#1]] +ExchangeSinkExec[[hire_date{f(DateEsField)}#0, $$order_by$0{r}#1],false] +\_ProjectExec[[_doc{f(EsField)}#2, $$order_by$0{r}#1]] \_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],36] \_EvalExec[[SIN(height{f}#3) * 2[INTEGER] AS $$order_by$0#1]] \_FieldExtractExec[height{f}#3]<[],[]> diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected index 9ce3f748778c1..3155ade77bff9 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[hire_date{f}#0, $$order_by$0{r}#1],false] +ExchangeSinkExec[[hire_date{f(DateEsField)}#0, $$order_by$0{r}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#2, $$order_by$0{r}#1]] +Project[[_doc{f(EsField)}#2, $$order_by$0{r}#1]] \_TopN[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],false] \_Eval[[SIN(height{f}#3) * 2[INTEGER] AS $$order_by$0#1]] \_EsRelation[employees][_doc{f}#2, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#3, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#0, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected index d2459818c5588..8a01de5d8a548 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[hire_date{f}#0, $$order_by$0{r}#1],false] -\_ProjectExec[[hire_date{f}#0, $$order_by$0{r}#1]] +ExchangeSinkExec[[hire_date{f(DateEsField)}#0, $$order_by$0{r}#1],false] +\_ProjectExec[[hire_date{f(DateEsField)}#0, $$order_by$0{r}#1]] \_FieldExtractExec[hire_date{f}#0]<[],[]> \_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#2, $$order_by$0{r}#1],false] \ No newline at end of file + \_ExchangeSourceExec[[_doc{f(EsField)}#2, $$order_by$0{r}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected index 71abdab6b07fe..1d2b47bd3d1a2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}#0]] +ProjectExec[[hire_date{f(DateEsField)}#0]] \_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[hire_date{f}#0, $$order_by$0{r}#1],false] + \_ExchangeExec[[hire_date{f(DateEsField)}#0, $$order_by$0{r}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[hire_date{f}#0, $$order_by$0{r}#1]] +Project[[hire_date{f(DateEsField)}#0, $$order_by$0{r}#1]] \_TopN[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],false] \_Eval[[SIN(height{f}#2) * 2[INTEGER] AS $$order_by$0#1]] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#2, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected index 460cbcab3451e..fa8fc973f782f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2],false] -\_ProjectExec[[_doc{f}#3, height{f}#0, $$order_by$0{r}#2]] +ExchangeSinkExec[[height{f(EsField)}#0, hire_date{f(DateEsField)}#1, $$order_by$0{r}#2],false] +\_ProjectExec[[_doc{f(EsField)}#3, height{f(EsField)}#0, $$order_by$0{r}#2]] \_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],36] \_EvalExec[[SIN(height{f}#0) * 2[INTEGER] AS $$order_by$0#2]] \_FieldExtractExec[height{f}#0]<[],[]> diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected index 932c4834e7e80..d650ee04b817e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2],false] +ExchangeSinkExec[[height{f(EsField)}#0, hire_date{f(DateEsField)}#1, $$order_by$0{r}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#3, height{f}#0, $$order_by$0{r}#2]] +Project[[_doc{f(EsField)}#3, height{f(EsField)}#0, $$order_by$0{r}#2]] \_TopN[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],false] \_Eval[[SIN(height{f}#0) * 2[INTEGER] AS $$order_by$0#2]] \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#0, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected index 88c85960c5dd2..ecc7f70c306ad 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2],false] -\_ProjectExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2]] +ExchangeSinkExec[[height{f(EsField)}#0, hire_date{f(DateEsField)}#1, $$order_by$0{r}#2],false] +\_ProjectExec[[height{f(EsField)}#0, hire_date{f(DateEsField)}#1, $$order_by$0{r}#2]] \_FieldExtractExec[hire_date{f}#1]<[],[]> \_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],44] - \_ExchangeSourceExec[[_doc{f}#3, height{f}#0, $$order_by$0{r}#2],false] \ No newline at end of file + \_ExchangeSourceExec[[_doc{f(EsField)}#3, height{f(EsField)}#0, $$order_by$0{r}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected index b3fbad771e03e..56453d62cad8f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}#0, height{f}#1]] +ProjectExec[[hire_date{f(DateEsField)}#0, height{f(EsField)}#1]] \_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[height{f}#1, hire_date{f}#0, $$order_by$0{r}#2],false] + \_ExchangeExec[[height{f(EsField)}#1, hire_date{f(DateEsField)}#0, $$order_by$0{r}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[height{f}#1, hire_date{f}#0, $$order_by$0{r}#2]] +Project[[height{f(EsField)}#1, hire_date{f(DateEsField)}#0, $$order_by$0{r}#2]] \_TopN[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],false] \_Eval[[SIN(height{f}#1) * 2[INTEGER] AS $$order_by$0#2]] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#1, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected index ebbbae1cfcc6d..ea2943054fab9 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected @@ -1,9 +1,9 @@ -ExchangeSinkExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] -\_ProjectExec[[_doc{f}#25, emp_no{f}#2, languages{f}#12, language_code{r}#23, language_name{f}#24]] - \_TopNExec[[Order[emp_no{f}#2,ASC,LAST]],20[INTEGER],82] +ExchangeSinkExec[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2, first_name{f(KeywordEsField)}#3, gender{f(KeywordEsField)}#4, height{f(EsField)}#5, height.float{f(EsField)}#6, height.half_float{f(EsField)}#7, height.scaled_float{f(EsField)}#8, hire_date{f(DateEsField)}#9, is_rehired{f(EsField)}#10, job_positions{f(KeywordEsField)}#11, languages{f(EsField)}#12, languages.byte{f(EsField)}#13, languages.long{f(EsField)}#14, languages.short{f(EsField)}#15, last_name{f(KeywordEsField)}#16, salary{f(EsField)}#17, salary_change{f(EsField)}#18, salary_change.int{f(EsField)}#19, salary_change.keyword{f(KeywordEsField)}#20, salary_change.long{f(EsField)}#21, still_hired{f(EsField)}#22, language_code{r}#23, language_name{f(KeywordEsField)}#24],false] +\_ProjectExec[[_doc{f(EsField)}#25, emp_no{f(EsField)}#2, languages{f(EsField)}#12, language_code{r}#23, language_name{f(KeywordEsField)}#24]] + \_TopNExec[[Order[emp_no{f(EsField)}#2,ASC,LAST]],20[INTEGER],82] \_FieldExtractExec[emp_no{f}#2]<[],[]> - \_LookupJoinExec[[language_code{r}#23],[language_code{f}#26],[language_name{f}#24],null] - |_EvalExec[[languages{f}#12 AS language_code#23]] + \_LookupJoinExec[[language_code{r}#23],[language_code{f(EsField)}#26],[language_name{f(KeywordEsField)}#24],null] + |_EvalExec[[languages{f(EsField)}#12 AS language_code#23]] | \_FieldExtractExec[languages{f}#12]<[],[]> | \_EsQueryExec[employees], indexMode[standard], [_doc{f}#25], limit[], sort[] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected index 7ff68ac134d83..35c83372e097e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected @@ -1,9 +1,9 @@ -ExchangeSinkExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] +ExchangeSinkExec[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2, first_name{f(KeywordEsField)}#3, gender{f(KeywordEsField)}#4, height{f(EsField)}#5, height.float{f(EsField)}#6, height.half_float{f(EsField)}#7, height.scaled_float{f(EsField)}#8, hire_date{f(DateEsField)}#9, is_rehired{f(EsField)}#10, job_positions{f(KeywordEsField)}#11, languages{f(EsField)}#12, languages.byte{f(EsField)}#13, languages.long{f(EsField)}#14, languages.short{f(EsField)}#15, last_name{f(KeywordEsField)}#16, salary{f(EsField)}#17, salary_change{f(EsField)}#18, salary_change.int{f(EsField)}#19, salary_change.keyword{f(KeywordEsField)}#20, salary_change.long{f(EsField)}#21, still_hired{f(EsField)}#22, language_code{r}#23, language_name{f(KeywordEsField)}#24],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#25, emp_no{f}#2, languages{f}#12, language_code{r}#23, language_name{f}#24]] -\_TopN[[Order[emp_no{f}#2,ASC,LAST]],20[INTEGER],false] - \_Join[LEFT,[language_code{r}#23],[language_code{f}#26],null] - |_Eval[[languages{f}#12 AS language_code#23]] +Project[[_doc{f(EsField)}#25, emp_no{f(EsField)}#2, languages{f(EsField)}#12, language_code{r}#23, language_name{f(KeywordEsField)}#24]] +\_TopN[[Order[emp_no{f(EsField)}#2,ASC,LAST]],20[INTEGER],false] + \_Join[LEFT,[language_code{r}#23],[language_code{f(EsField)}#26],null] + |_Eval[[languages{f(EsField)}#12 AS language_code#23]] | \_Filter[emp_no{f}#2 >= 10091[INTEGER] AND emp_no{f}#2 < 10094[INTEGER]] | \_EsRelation[employees][_doc{f}#25, avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22] \_EsRelation[languages_lookup][LOOKUP][language_code{f}#26, language_name{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected index 19c98b1780f37..d6ecc720cbde4 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] -\_ProjectExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24]] +ExchangeSinkExec[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2, first_name{f(KeywordEsField)}#3, gender{f(KeywordEsField)}#4, height{f(EsField)}#5, height.float{f(EsField)}#6, height.half_float{f(EsField)}#7, height.scaled_float{f(EsField)}#8, hire_date{f(DateEsField)}#9, is_rehired{f(EsField)}#10, job_positions{f(KeywordEsField)}#11, languages{f(EsField)}#12, languages.byte{f(EsField)}#13, languages.long{f(EsField)}#14, languages.short{f(EsField)}#15, last_name{f(KeywordEsField)}#16, salary{f(EsField)}#17, salary_change{f(EsField)}#18, salary_change.int{f(EsField)}#19, salary_change.keyword{f(KeywordEsField)}#20, salary_change.long{f(EsField)}#21, still_hired{f(EsField)}#22, language_code{r}#23, language_name{f(KeywordEsField)}#24],false] +\_ProjectExec[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2, first_name{f(KeywordEsField)}#3, gender{f(KeywordEsField)}#4, height{f(EsField)}#5, height.float{f(EsField)}#6, height.half_float{f(EsField)}#7, height.scaled_float{f(EsField)}#8, hire_date{f(DateEsField)}#9, is_rehired{f(EsField)}#10, job_positions{f(KeywordEsField)}#11, languages{f(EsField)}#12, languages.byte{f(EsField)}#13, languages.long{f(EsField)}#14, languages.short{f(EsField)}#15, last_name{f(KeywordEsField)}#16, salary{f(EsField)}#17, salary_change{f(EsField)}#18, salary_change.int{f(EsField)}#19, salary_change.keyword{f(KeywordEsField)}#20, salary_change.long{f(EsField)}#21, still_hired{f(EsField)}#22, language_code{r}#23, language_name{f(KeywordEsField)}#24]] \_FieldExtractExec[avg_worked_seconds{f}#0, birth_date{f}#1, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<[],[]> - \_TopNExec[[Order[emp_no{f}#2,ASC,LAST]],20[INTEGER],430] - \_ExchangeSourceExec[[_doc{f}#25, emp_no{f}#2, languages{f}#12, language_code{r}#23, language_name{f}#24],false] \ No newline at end of file + \_TopNExec[[Order[emp_no{f(EsField)}#2,ASC,LAST]],20[INTEGER],430] + \_ExchangeSourceExec[[_doc{f(EsField)}#25, emp_no{f(EsField)}#2, languages{f(EsField)}#12, language_code{r}#23, language_name{f(KeywordEsField)}#24],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected index 438c1c6d34382..dcc47c1a23fed 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected @@ -1,10 +1,10 @@ -TopNExec[[Order[emp_no{f}#0,ASC,LAST]],20[INTEGER],null] -\_ExchangeExec[[avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#0, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] +TopNExec[[Order[emp_no{f(EsField)}#0,ASC,LAST]],20[INTEGER],null] +\_ExchangeExec[[avg_worked_seconds{f(EsField)}#1, birth_date{f(DateEsField)}#2, emp_no{f(EsField)}#0, first_name{f(KeywordEsField)}#3, gender{f(KeywordEsField)}#4, height{f(EsField)}#5, height.float{f(EsField)}#6, height.half_float{f(EsField)}#7, height.scaled_float{f(EsField)}#8, hire_date{f(DateEsField)}#9, is_rehired{f(EsField)}#10, job_positions{f(KeywordEsField)}#11, languages{f(EsField)}#12, languages.byte{f(EsField)}#13, languages.long{f(EsField)}#14, languages.short{f(EsField)}#15, last_name{f(KeywordEsField)}#16, salary{f(EsField)}#17, salary_change{f(EsField)}#18, salary_change.int{f(EsField)}#19, salary_change.keyword{f(KeywordEsField)}#20, salary_change.long{f(EsField)}#21, still_hired{f(EsField)}#22, language_code{r}#23, language_name{f(KeywordEsField)}#24],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#0, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24]] -\_TopN[[Order[emp_no{f}#0,ASC,LAST]],20[INTEGER],false] - \_Join[LEFT,[language_code{r}#23],[language_code{f}#25],null] - |_Eval[[languages{f}#12 AS language_code#23]] +Project[[avg_worked_seconds{f(EsField)}#1, birth_date{f(DateEsField)}#2, emp_no{f(EsField)}#0, first_name{f(KeywordEsField)}#3, gender{f(KeywordEsField)}#4, height{f(EsField)}#5, height.float{f(EsField)}#6, height.half_float{f(EsField)}#7, height.scaled_float{f(EsField)}#8, hire_date{f(DateEsField)}#9, is_rehired{f(EsField)}#10, job_positions{f(KeywordEsField)}#11, languages{f(EsField)}#12, languages.byte{f(EsField)}#13, languages.long{f(EsField)}#14, languages.short{f(EsField)}#15, last_name{f(KeywordEsField)}#16, salary{f(EsField)}#17, salary_change{f(EsField)}#18, salary_change.int{f(EsField)}#19, salary_change.keyword{f(KeywordEsField)}#20, salary_change.long{f(EsField)}#21, still_hired{f(EsField)}#22, language_code{r}#23, language_name{f(KeywordEsField)}#24]] +\_TopN[[Order[emp_no{f(EsField)}#0,ASC,LAST]],20[INTEGER],false] + \_Join[LEFT,[language_code{r}#23],[language_code{f(EsField)}#25],null] + |_Eval[[languages{f(EsField)}#12 AS language_code#23]] | \_Filter[emp_no{f}#0 >= 10091[INTEGER] AND emp_no{f}#0 < 10094[INTEGER]] | \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#0, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22] \_EsRelation[languages_lookup][LOOKUP][language_code{f}#25, language_name{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected index e5de0b72a7705..f7582a56ce920 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2],false] -\_ProjectExec[[_doc{f}#3, hire_date{f}#2, height{f}#1]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1, hire_date{f(DateEsField)}#2],false] +\_ProjectExec[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#2, height{f(EsField)}#1]] \_FieldExtractExec[hire_date{f}#2, height{f}#1]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#2, direction=ASC, nulls=LAST], FieldSort[field=height{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[32] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected index 4866ac15c30c3..b003dc8e5c04a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2],false] +ExchangeSinkExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1, hire_date{f(DateEsField)}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#3, hire_date{f}#2, height{f}#1]] -\_TopN[[Order[hire_date{f}#2,ASC,LAST], Order[height{f}#1,ASC,LAST]],20[INTEGER],false] +Project[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#2, height{f(EsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#2,ASC,LAST], Order[height{f(EsField)}#1,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#1, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#2, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected index ab96def3b448c..c9edf368a9a02 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2],false] -\_ProjectExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1, hire_date{f(DateEsField)}#2],false] +\_ProjectExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1, hire_date{f(DateEsField)}#2]] \_FieldExtractExec[emp_no{f}#0]<[],[]> - \_TopNExec[[Order[hire_date{f}#2,ASC,LAST], Order[height{f}#1,ASC,LAST]],20[INTEGER],40] - \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#2, height{f}#1],false] \ No newline at end of file + \_TopNExec[[Order[hire_date{f(DateEsField)}#2,ASC,LAST], Order[height{f(EsField)}#1,ASC,LAST]],20[INTEGER],40] + \_ExchangeSourceExec[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#2, height{f(EsField)}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected index 64df823ba0bbf..c2f87bb079ce4 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[hire_date{f}#0, emp_no{f}#1, height{f}#2]] -\_TopNExec[[Order[hire_date{f}#0,ASC,LAST], Order[height{f}#2,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}#1, height{f}#2, hire_date{f}#0],false] +ProjectExec[[hire_date{f(DateEsField)}#0, emp_no{f(EsField)}#1, height{f(EsField)}#2]] +\_TopNExec[[Order[hire_date{f(DateEsField)}#0,ASC,LAST], Order[height{f(EsField)}#2,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f(EsField)}#1, height{f(EsField)}#2, hire_date{f(DateEsField)}#0],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#1, height{f}#2, hire_date{f}#0]] -\_TopN[[Order[hire_date{f}#0,ASC,LAST], Order[height{f}#2,ASC,LAST]],20[INTEGER],false] +Project[[emp_no{f(EsField)}#1, height{f(EsField)}#2, hire_date{f(DateEsField)}#0]] +\_TopN[[Order[hire_date{f(DateEsField)}#0,ASC,LAST], Order[height{f(EsField)}#2,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#1, first_name{f}#5, gender{f}#6, height{f}#2, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#0, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected index 71c01677f83a5..535953e39d9cf 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[_doc{f}#3, hire_date{f}#1]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] +\_ProjectExec[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#1]] \_FieldExtractExec[hire_date{f}#1]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected index fc4d011c9a8fb..6b9bd659d3727 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#3, hire_date{f}#1]] -\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] +Project[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected index 4b4fc0c891ac1..b4351eb176c15 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] +\_ProjectExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2]] \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> - \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file + \_TopNExec[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected index 92cf16635a7dc..8cf112d600609 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] -\_TopNExec[[Order[salary{f}#1,ASC,LAST]],10[INTEGER],null] - \_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] +ProjectExec[[hire_date{f(DateEsField)}#0, salary{f(EsField)}#1, emp_no{f(EsField)}#2]] +\_TopNExec[[Order[salary{f(EsField)}#1,ASC,LAST]],10[INTEGER],null] + \_TopNExec[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] -\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] +Project[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected index f0d827b7d0c99..17985e6fc7ff0 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,7 +1,7 @@ -ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2]] - \_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] - \_MvExpandExec[job_positions{f}#3,job_positions{r}#1] - \_ProjectExec[[emp_no{f}#0, job_positions{f}#3, salary{f}#2]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2],false] +\_ProjectExec[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2]] + \_TopNExec[[Order[salary{f(EsField)}#2,ASC,LAST]],20[INTEGER],58] + \_MvExpandExec[job_positions{f(KeywordEsField)}#3,job_positions{r}#1] + \_ProjectExec[[emp_no{f(EsField)}#0, job_positions{f(KeywordEsField)}#3, salary{f(EsField)}#2]] \_FieldExtractExec[emp_no{f}#0, job_positions{f}#3, salary{f}#2]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#4], limit[], sort[] estimatedRowSize[62] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected index a9639e399dec8..5932932aa8946 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected @@ -1,3 +1,3 @@ -ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] -\_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] - \_ExchangeSourceExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2],false] +\_TopNExec[[Order[salary{f(EsField)}#2,ASC,LAST]],20[INTEGER],58] + \_ExchangeSourceExec[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected index baf5e66932990..5f94092df9787 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected @@ -1,7 +1,7 @@ -ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] +ExchangeSinkExec[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#0, job_positions{r}#1, salary{f}#2]] -\_TopN[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],false] - \_MvExpand[job_positions{f}#3,job_positions{r}#1] - \_Project[[emp_no{f}#0, job_positions{f}#3, salary{f}#2]] +Project[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2]] +\_TopN[[Order[salary{f(EsField)}#2,ASC,LAST]],20[INTEGER],false] + \_MvExpand[job_positions{f(KeywordEsField)}#3,job_positions{r}#1] + \_Project[[emp_no{f(EsField)}#0, job_positions{f(KeywordEsField)}#3, salary{f(EsField)}#2]] \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#3, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected index a9639e399dec8..5932932aa8946 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected @@ -1,3 +1,3 @@ -ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] -\_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] - \_ExchangeSourceExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2],false] +\_TopNExec[[Order[salary{f(EsField)}#2,ASC,LAST]],20[INTEGER],58] + \_ExchangeSourceExec[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected index 7bd205fddb3bd..5f66a7ee4c49f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected @@ -1,8 +1,8 @@ -TopNExec[[Order[salary{f}#0,ASC,LAST]],20[INTEGER],null] -\_ExchangeExec[[emp_no{f}#1, job_positions{r}#2, salary{f}#0],false] +TopNExec[[Order[salary{f(EsField)}#0,ASC,LAST]],20[INTEGER],null] +\_ExchangeExec[[emp_no{f(EsField)}#1, job_positions{r}#2, salary{f(EsField)}#0],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#1, job_positions{r}#2, salary{f}#0]] -\_TopN[[Order[salary{f}#0,ASC,LAST]],20[INTEGER],false] - \_MvExpand[job_positions{f}#3,job_positions{r}#2] - \_Project[[emp_no{f}#1, job_positions{f}#3, salary{f}#0]] +Project[[emp_no{f(EsField)}#1, job_positions{r}#2, salary{f(EsField)}#0]] +\_TopN[[Order[salary{f(EsField)}#0,ASC,LAST]],20[INTEGER],false] + \_MvExpand[job_positions{f(KeywordEsField)}#3,job_positions{r}#2] + \_Project[[emp_no{f(EsField)}#1, job_positions{f(KeywordEsField)}#3, salary{f(EsField)}#0]] \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#1, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#3, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#0, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected index cebf3f704c28d..1a1dccc05bae7 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[emp_no{f}#0, height{f}#1],false] -\_ProjectExec[[_doc{f}#2, height{f}#1]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1],false] +\_ProjectExec[[_doc{f(EsField)}#2, height{f(EsField)}#1]] \_FieldExtractExec[height{f}#1]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#2], limit[20], sort[[FieldSort[field=height{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected index b2913dbdf505b..65dae554c74ef 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, height{f}#1],false] +ExchangeSinkExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#2, height{f}#1]] -\_TopN[[Order[height{f}#1,ASC,LAST]],20[INTEGER],false] +Project[[_doc{f(EsField)}#2, height{f(EsField)}#1]] +\_TopN[[Order[height{f(EsField)}#1,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][_doc{f}#2, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#0, first_name{f}#5, gender{f}#6, height{f}#1, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected index 3425364e715c1..3633dfb6c48db 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, height{f}#1],false] -\_ProjectExec[[emp_no{f}#0, height{f}#1]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1],false] +\_ProjectExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1]] \_FieldExtractExec[emp_no{f}#0]<[],[]> - \_TopNExec[[Order[height{f}#1,ASC,LAST]],20[INTEGER],32] - \_ExchangeSourceExec[[_doc{f}#2, height{f}#1],false] \ No newline at end of file + \_TopNExec[[Order[height{f(EsField)}#1,ASC,LAST]],20[INTEGER],32] + \_ExchangeSourceExec[[_doc{f(EsField)}#2, height{f(EsField)}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected index e659e9ce08d64..66a0e8e8c2995 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[emp_no{f}#0, height{f}#1]] -\_TopNExec[[Order[height{f}#1,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}#0, height{f}#1],false] +ProjectExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1]] +\_TopNExec[[Order[height{f(EsField)}#1,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#0, height{f}#1]] -\_TopN[[Order[height{f}#1,ASC,LAST]],20[INTEGER],false] +Project[[emp_no{f(EsField)}#0, height{f(EsField)}#1]] +\_TopN[[Order[height{f(EsField)}#1,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#0, first_name{f}#4, gender{f}#5, height{f}#1, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected index 91fa3beaa5567..2bf1f8cfb7f44 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[_doc{f}#3, salary{f}#2, hire_date{f}#1]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] +\_ProjectExec[[_doc{f(EsField)}#3, salary{f(EsField)}#2, hire_date{f(DateEsField)}#1]] \_FieldExtractExec[salary{f}#2, hire_date{f}#1]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected index 1e90a18573c7c..54d4c418762b0 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#3, salary{f}#2, hire_date{f}#1]] -\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] +Project[[_doc{f(EsField)}#3, salary{f(EsField)}#2, hire_date{f(DateEsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],false] \_Filter[salary{f}#2 > 10000[INTEGER]] \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected index 178d31ccc5dc1..22b9264fc278a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] +\_ProjectExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2]] \_FieldExtractExec[emp_no{f}#0]<[],[]> - \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#3, salary{f}#2, hire_date{f}#1],false] \ No newline at end of file + \_TopNExec[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f(EsField)}#3, salary{f(EsField)}#2, hire_date{f(DateEsField)}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected index 6fc12a53e3980..4b4f50ecdb071 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] -\_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] +ProjectExec[[hire_date{f(DateEsField)}#0, salary{f(EsField)}#1, emp_no{f(EsField)}#2]] +\_TopNExec[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] -\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] +Project[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],false] \_Filter[salary{f}#1 > 10000[INTEGER]] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected index 8dc76dd8b28df..6dafad051ff32 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[hire_date{f}#0, salary{f}#1],false] -\_ProjectExec[[_doc{f}#2, hire_date{f}#0]] +ExchangeSinkExec[[hire_date{f(DateEsField)}#0, salary{f(EsField)}#1],false] +\_ProjectExec[[_doc{f(EsField)}#2, hire_date{f(DateEsField)}#0]] \_FieldExtractExec[hire_date{f}#0]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#2], limit[20], sort[[FieldSort[field=hire_date{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected index 070d12cb17d93..65eaafe17c343 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[hire_date{f}#0, salary{f}#1],false] +ExchangeSinkExec[[hire_date{f(DateEsField)}#0, salary{f(EsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#2, hire_date{f}#0]] -\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] +Project[[_doc{f(EsField)}#2, hire_date{f(DateEsField)}#0]] +\_TopN[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][_doc{f}#2, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#0, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#1, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected index 3c81025a6c14e..a0f7bfca2eddb 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[hire_date{f}#0, salary{f}#1],false] -\_ProjectExec[[hire_date{f}#0, salary{f}#1]] +ExchangeSinkExec[[hire_date{f(DateEsField)}#0, salary{f(EsField)}#1],false] +\_ProjectExec[[hire_date{f(DateEsField)}#0, salary{f(EsField)}#1]] \_FieldExtractExec[salary{f}#1]<[],[]> - \_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],32] - \_ExchangeSourceExec[[_doc{f}#2, hire_date{f}#0],false] \ No newline at end of file + \_TopNExec[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],32] + \_ExchangeSourceExec[[_doc{f(EsField)}#2, hire_date{f(DateEsField)}#0],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected index d520dec0664bd..9aac8fbe309dd 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected @@ -1,10 +1,10 @@ ProjectExec[[avg_salary{r}#0, count{r}#1]] \_EvalExec[[$$SUM$avg_salary$0{r$}#2 / $$COUNT$avg_salary$1{r$}#3 AS avg_salary#0]] \_LimitExec[10000[INTEGER],null] - \_AggregateExec[[],[SUM(salary{f}#4,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS $$SUM$avg_salary$0#2, COUNT(salary{f}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS $$COUNT$avg_salary$1#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count#1],SINGLE,[$$SUM$avg_salary$0$sum{r}#5, $$SUM$avg_salary$0$seen{r}#6, $$COUNT$avg_salary$1$count{r}#7, $$COUNT$avg_salary$1$seen{r}#8, $$count$count{r}#9, $$count$seen{r}#10],null] - \_TopNExec[[Order[hire_date{f}#11,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[hire_date{f}#11, salary{f}#4],false] + \_AggregateExec[[],[SUM(salary{f(EsField)}#4,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS $$SUM$avg_salary$0#2, COUNT(salary{f(EsField)}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS $$COUNT$avg_salary$1#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count#1],SINGLE,[$$SUM$avg_salary$0$sum{r}#5, $$SUM$avg_salary$0$seen{r}#6, $$COUNT$avg_salary$1$count{r}#7, $$COUNT$avg_salary$1$seen{r}#8, $$count$count{r}#9, $$count$seen{r}#10],null] + \_TopNExec[[Order[hire_date{f(DateEsField)}#11,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[hire_date{f(DateEsField)}#11, salary{f(EsField)}#4],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[hire_date{f}#11, salary{f}#4]] -\_TopN[[Order[hire_date{f}#11,ASC,LAST]],20[INTEGER],false] +Project[[hire_date{f(DateEsField)}#11, salary{f(EsField)}#4]] +\_TopN[[Order[hire_date{f(DateEsField)}#11,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][avg_worked_seconds{f}#12, birth_date{f}#13, emp_no{f}#14, first_name{f}#15, gender{f}#16, height{f}#17, height.float{f}#18, height.half_float{f}#19, height.scaled_float{f}#20, hire_date{f}#11, is_rehired{f}#21, job_positions{f}#22, languages{f}#23, languages.byte{f}#24, languages.long{f}#25, languages.short{f}#26, last_name{f}#27, salary{f}#4, salary_change{f}#28, salary_change.int{f}#29, salary_change.keyword{f}#30, salary_change.long{f}#31, still_hired{f}#32]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected index 0280707cf7711..94b31f194f9c6 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[_doc{f}#3, birth_date{r}#4 AS hire_date#1]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] +\_ProjectExec[[_doc{f(EsField)}#3, birth_date{r}#4 AS hire_date#1]] \_EvalExec[[null[DATETIME] AS birth_date#4]] \_EsQueryExec[employees], indexMode[standard], [_doc{f}#3], limit[20], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected index fc4d011c9a8fb..6b9bd659d3727 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#3, hire_date{f}#1]] -\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] +Project[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][_doc{f}#3, avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#1, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected index 4b4fc0c891ac1..b4351eb176c15 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] +\_ProjectExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2]] \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> - \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file + \_TopNExec[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected index 84b502cae4e25..fac7b0beb280e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] -\_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] +ProjectExec[[hire_date{f(DateEsField)}#0, salary{f(EsField)}#1, emp_no{f(EsField)}#2]] +\_TopNExec[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] -\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] +Project[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file From 66cb1ed607518e9032b87462e52c2030dfcb016e Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 5 Feb 2026 14:45:33 +0200 Subject: [PATCH 022/137] Add field aliases test --- .../src/main/resources/data/all-types.csv | 7 ++++++- .../src/main/resources/unmapped-load.csv-spec | 19 +++++++++++++++++++ .../xpack/esql/action/EsqlCapabilities.java | 5 +++++ .../elasticsearch/xpack/esql/CsvTests.java | 4 ++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/data/all-types.csv b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/data/all-types.csv index b6447d688c9d1..cdb40caa14a81 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/data/all-types.csv +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/data/all-types.csv @@ -1 +1,6 @@ -alias_integer,boolean,byte,constant_keyword-foo,date,date_nanos,double,float,half_float,scaled_float,integer,ip,keyword,long,unsigned_long,short,text,version,wildcard,semantic_text,dense_vector +boolean:boolean,byte:byte,constant_keyword-foo:keyword,date:date,date_nanos:date_nanos,double:double,float:float,half_float:half_float,scaled_float:scaled_float,integer:integer,ip:ip,keyword:keyword,long:long,unsigned_long:unsigned_long,short:short,text:text,version:version,wildcard:keyword +true,1,foo,2024-01-01T00:00:00.000Z,2024-01-01T00:00:00.000000001Z,1.1,1.1,1.1,1.1,1,127.0.0.1,key1,100,100,10,text1,1.0.0,wild1 +false,2,foo,2024-01-02T00:00:00.000Z,2024-01-02T00:00:00.000000002Z,2.2,2.2,2.2,2.2,2,127.0.0.2,key2,200,200,20,text2,2.0.0,wild2 +true,3,foo,2024-01-03T00:00:00.000Z,2024-01-03T00:00:00.000000003Z,3.3,3.3,3.3,3.3,3,127.0.0.3,key3,300,300,30,text3,3.0.0,wild3 +false,4,foo,2024-01-04T00:00:00.000Z,2024-01-04T00:00:00.000000004Z,4.4,4.4,4.4,4.4,4,127.0.0.4,key4,400,400,40,text4,4.0.0,wild4 +true,5,foo,2024-01-05T00:00:00.000Z,2024-01-05T00:00:00.000000005Z,5.5,5.5,5.5,5.5,5,127.0.0.5,key5,500,500,50,text5,5.0.0,wild5 diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index b2fff4ffb70b2..d0b808a601540 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -729,3 +729,22 @@ count(*):long | message::INT:integer 13 | null 1 | 42 ; + +fieldAliasAndNonExistent +required_capability: unmapped_fields +required_capability: optional_fields +required_capability: field_alias_support + +SET unmapped_fields="load"\; +FROM all_types +| KEEP integer, alias_integer, does_not_exist +| SORT integer +; + +integer:integer | alias_integer:integer | does_not_exist:keyword +1 | 1 | null +2 | 2 | null +3 | 3 | null +4 | 4 | null +5 | 5 | null +; 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 45b41b9be7b5e..628fb1d47bd5d 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 @@ -845,6 +845,11 @@ public enum Cap { */ SOURCE_FIELD_MAPPING, + /** + * Support for field aliases in mappings. + */ + FIELD_ALIAS_SUPPORT, + /** * Allow filter per individual aggregation. */ diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java index 168963a616950..bb3eb9518bd29 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java @@ -350,6 +350,10 @@ public final void test() throws Throwable { "CSV tests cannot currently handle the _source field mapping directives", testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.SOURCE_FIELD_MAPPING.capabilityName()) ); + assumeFalseLogging( + "CSV tests cannot currently handle field aliases in mappings", + testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.FIELD_ALIAS_SUPPORT.capabilityName()) + ); assumeFalseLogging( "CSV tests cannot currently handle scoring that depends on Lucene", testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.METADATA_SCORE.capabilityName()) From 221c4fadfafb16ae2bba149202d13687c512fb04 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 5 Feb 2026 21:06:16 +0200 Subject: [PATCH 023/137] Stuffs --- .../esql/core/expression/FieldAttribute.java | 1 - .../xpack/esql/core/tree/NodeUtils.java | 1 - .../analysis/AnalyzerUnmappedGoldenTests.java | 117 +++++++++++++----- .../esql/analysis/AnalyzerUnmappedTests.java | 53 ++++++++ .../xpack/esql/optimizer/GoldenTestCase.java | 26 ++-- .../load/analysis.expected | 3 + .../load/query.esql | 2 + .../nullify/analysis.expected | 3 + .../nullify/query.esql | 2 + .../load/analysis.expected | 4 + .../load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../nullify/query.esql | 2 +- .../load/analysis.expected | 5 + .../load/query.esql | 3 + .../nullify/analysis.expected | 6 + .../nullify/query.esql | 3 + .../load/analysis.expected | 5 + .../load/query.esql | 3 + .../nullify/analysis.expected | 6 + .../nullify/query.esql | 3 + .../testFuse/load/analysis.expected | 15 +++ .../testFuse/load/query.esql | 4 + .../testFuse/nullify/analysis.expected | 16 +++ .../testFuse/nullify/query.esql | 4 + .../testFuseLinear/load/analysis.expected | 18 +++ .../testFuseLinear/load/query.esql | 4 + .../testFuseLinear/nullify/analysis.expected | 19 +++ .../testFuseLinear/nullify/query.esql | 4 + .../testFuseWithEval/load/analysis.expected | 16 +++ .../testFuseWithEval/load/query.esql | 4 + .../nullify/analysis.expected | 17 +++ .../testFuseWithEval/nullify/query.esql | 4 + .../testKeep/load/analysis.expected | 5 +- .../testKeep/load/query.esql | 3 +- .../testKeep/nullify/analysis.expected | 7 +- .../testKeep/nullify/query.esql | 3 +- .../testLookupJoin/load/query.esql | 2 +- .../testLookupJoin/nullify/query.esql | 2 +- .../load/analysis.expected | 3 + .../testMappedInOneIndexOnly/load/query.esql | 2 + .../nullify/analysis.expected | 3 + .../nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../load/query.esql | 2 + .../nullify/analysis.expected | 3 + .../nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../load/query.esql | 2 + .../nullify/analysis.expected | 3 + .../nullify/query.esql | 2 + .../load/analysis.expected | 4 + .../load/query.esql | 2 + .../nullify/analysis.expected | 3 + .../nullify/query.esql | 2 + .../testSubqueryKeep/load/query.esql | 3 + .../testSubqueryKeep/nullify/query.esql | 3 + .../load/analysis.expected | 18 +-- .../testSubqueryKeepUnmapped/load/query.esql | 2 +- .../nullify/analysis.expected | 12 +- .../nullify/query.esql | 2 +- .../load/query.esql | 2 + .../nullify/query.esql | 2 + .../sql/qa/server/src/main/resources/apps.csv | 2 +- 65 files changed, 420 insertions(+), 70 deletions(-) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/nullify/query.esql diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/FieldAttribute.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/FieldAttribute.java index 28dec3ad94a2a..14e1e9c6c094d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/FieldAttribute.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/FieldAttribute.java @@ -275,7 +275,6 @@ public EsField field() { @Override public String nodeString(NodeStringFormat format) { return switch (format) { - // FIXME(gal, NOCOMMIT) unhack case FULL -> Strings.format( "%s{%s(%s)%s}#%s".formatted(qualifiedName(), label(), field.getWriteableName(), synthetic() ? "$" : "", id()) ); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/tree/NodeUtils.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/tree/NodeUtils.java index ed453bedbacf6..6874b869ec872 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/tree/NodeUtils.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/tree/NodeUtils.java @@ -62,7 +62,6 @@ public static String diffString(String left, String right) { public static String toString(Collection c, Node.NodeStringFormat format) { return switch (format) { case LIMITED -> limitedToString(c); - // FIXME(gal, NOCOMMIT) This need to pass format to c as well case FULL -> unlimitedToString(c); }; } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java index 089a16a868bef..8aad5cdec6b1c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -11,8 +11,7 @@ import org.elasticsearch.xpack.esql.optimizer.GoldenTestCase; import java.util.EnumSet; - -import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning; +import java.util.Optional; /** * Golden tests for analyzer behavior with unmapped fields using SET unmapped_fields="nullify" and "load". @@ -24,7 +23,8 @@ public class AnalyzerUnmappedGoldenTests extends GoldenTestCase { public void testKeep() throws Exception { runTests(""" FROM employees - | KEEP does_not_exist_field + | eval x = does_not_exist_field :: version + | keep x """); } @@ -164,6 +164,14 @@ public void testStatsBy() throws Exception { """); } + public void testDoesNotExistAfterInlineStats() throws Exception { + runTests(""" + FROM employees + | INLINE STATS COUNT(*) BY emp_no + | EVAL x = does_not_exist_field + """); + } + public void testStatsSumBy() throws Exception { runTests(""" FROM employees @@ -266,7 +274,7 @@ public void testMvExpand() throws Exception { public void testLookupJoin() throws Exception { runTests(""" FROM employees - | EVAL language_code = does_not_exist::INTEGER + | EVAL language_code = does_not_exist :: INTEGER | LOOKUP JOIN languages_lookup ON language_code """); } @@ -282,7 +290,7 @@ public void testLookupJoinWithFilter() throws Exception { public void testSubqueryKeepUnmapped() throws Exception { runTests(""" - FROM employees, (FROM languages | KEEP language_code, does_not_exist) + FROM employees, (FROM languages | KEEP language_code) | KEEP emp_no, language_code, does_not_exist """); } @@ -327,6 +335,36 @@ public void testForkWithStats() throws Exception { """); } + public void testFuse() throws Exception { + assumeTrue("requires FUSE capability", EsqlCapabilities.Cap.FUSE_V6.isEnabled()); + runTests(""" + FROM employees METADATA _score, _index, _id + | FORK (WHERE does_not_exist::LONG > 0) + (WHERE emp_no > 0) + | FUSE + """); + } + + public void testFuseWithEval() throws Exception { + assumeTrue("requires FUSE capability", EsqlCapabilities.Cap.FUSE_V6.isEnabled()); + runTests(""" + FROM employees METADATA _score, _index, _id + | FORK (EVAL x = does_not_exist::DOUBLE + 1) + (EVAL y = emp_no + 1) + | FUSE RRF + """); + } + + public void testFuseLinear() throws Exception { + assumeTrue("requires FUSE capability", EsqlCapabilities.Cap.FUSE_V6.isEnabled()); + runTests(""" + FROM employees METADATA _score, _index, _id + | FORK (WHERE does_not_exist::LONG > 0 | EVAL x = 1) + (WHERE emp_no > 0 | EVAL y = 2) + | FUSE LINEAR + """); + } + public void testCoalesce() throws Exception { runTests(""" FROM employees @@ -356,8 +394,6 @@ public void testTimeSeriesRateUnmapped() throws Exception { """); } - // TODO add one for text - public void testTimeSeriesFirstOverTimeUnmapped() throws Exception { runTests(""" TS k8s @@ -372,39 +408,47 @@ public void testPartiallyMappedField() throws Exception { """); } - public void testPartiallyMappedFieldWithStats() throws Exception { + public void testMappedInOneIndexOnly() throws Exception { runTests(""" - FROM sample_data, partial_mapping_sample_data - | STATS c = COUNT(*) BY unmapped_message + FROM sample_data, no_mapping_sample_data + | KEEP message """); } - public void testPartiallyMappedFieldWithEval() throws Exception { + public void testMappedInOneIndexOnlyCast() throws Exception { runTests(""" - FROM sample_data, partial_mapping_sample_data - | EVAL x = COALESCE(unmapped_message, "missing") - | KEEP @timestamp, x, does_not_exist + FROM sample_data, no_mapping_sample_data + | EVAL x = message :: LONG """); } - public void testDifferentTypesAcrossIndices() throws Exception { + public void testMappedToNonKeywordInOneIndexOnly() throws Exception { runTests(""" - FROM sample_data, sample_data_ts_long - | KEEP @timestamp, message, does_not_exist + FROM sample_data, no_mapping_sample_data + | KEEP event_duration """); } - public void testDifferentTypesWithCast() throws Exception { + @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/pull/141912") + public void testMappedToNonKeywordInOneIndexOnlyCast() throws Exception { runTests(""" - FROM sample_data, sample_data_ts_long - | EVAL ts = @timestamp::STRING - | KEEP ts, message, does_not_exist + FROM sample_data, no_mapping_sample_data + | EVAL x = event_duration :: DOUBLE """); } - @Override - protected java.util.List filteredWarnings() { - return withDefaultLimitWarning(super.filteredWarnings()); + public void testDifferentTypesAndUnmapped() throws Exception { + runTests(""" + FROM sample_data, sample_data_ts_long, no_mapping_sample_data + | KEEP @timestamp + """); + } + + public void testDifferentTypesAndUnmappedCast() throws Exception { + runTests(""" + FROM sample_data, sample_data_ts_long, no_mapping_sample_data + | EVAL x = @timestamp :: DOUBLE + """); } private static String setUnmappedNullify(String query) { @@ -416,15 +460,26 @@ private static String setUnmappedLoad(String query) { } private void runTests(String query) { - runTestsNullifyOnly(query); - if (EsqlCapabilities.Cap.OPTIONAL_FIELDS.isEnabled()) { - builder(setUnmappedLoad(query)).nestedPath("load").stages(STAGES).run(); + var nullifyException = runTestsNullifyOnly(query); + var loadException = runTestsLoadOnly(query); + if (nullifyException.isPresent() && loadException.isPresent()) { + throw new AssertionError("Both nullify and load modes failed", nullifyException.get()); + } else if (nullifyException.isPresent()) { + throw new AssertionError("Nullify mode failed (but load succeeded)", nullifyException.get()); + } else if (loadException.isPresent()) { + throw new AssertionError("Load mode failed (but nullify succeeded)", loadException.get()); } } - private void runTestsNullifyOnly(String query) { - if (EsqlCapabilities.Cap.OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW.isEnabled()) { - builder(setUnmappedNullify(query)).nestedPath("nullify").stages(STAGES).run(); - } + private Optional runTestsNullifyOnly(String query) { + return EsqlCapabilities.Cap.OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW.isEnabled() + ? builder(setUnmappedNullify(query)).nestedPath("nullify").stages(STAGES).tryRun() + : Optional.empty(); + } + + private Optional runTestsLoadOnly(String query) { + return EsqlCapabilities.Cap.OPTIONAL_FIELDS.isEnabled() + ? builder(setUnmappedLoad(query)).nestedPath("load").stages(STAGES).tryRun() + : Optional.empty(); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index d2b8bdf2af5bb..7c8d614902616 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -912,6 +912,17 @@ public void testFailStatsThenEval() { verificationFailure(setUnmappedLoad(query), failure); } + public void testFailStatsThenEvalExistingField() { + var query = """ + FROM test + | STATS cnt = COUNT(*) + | EVAL x = emp_no + """; + var failure = "line 3:12: Unknown column [emp_no]"; + verificationFailure(setUnmappedNullify(query), failure); + verificationFailure(setUnmappedLoad(query), failure); + } + /* * Limit[1000[INTEGER],false,false] * \_Aggregate[[],[COUNT(does_not_exist_field{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt#5]] @@ -3193,6 +3204,17 @@ public void testLookupJoin() { assertThat(rightRel.indexPattern(), is("languages_lookup")); } + public void testFailLookupJoinWithoutCast() { + String query = """ + FROM test + | EVAL language_code = does_not_exist + | LOOKUP JOIN languages_lookup ON language_code + """; + var failure = "is incompatible with right field [language_code] of type [INTEGER]"; + verificationFailure(setUnmappedNullify(query), failure); + verificationFailure(setUnmappedLoad(query), failure); + } + /* * Limit[1000[INTEGER],false,false] * \_Enrich[ANY,languages[KEYWORD],x{r}#5,{"match":{"indices":[],"match_field":"language_code", @@ -3268,6 +3290,26 @@ public void testSemanticText() { assertThat(relation.indexPattern(), is("test")); } + public void testFailSemanticTextLoad() { + String query = """ + FROM test + | WHERE KNN(does_not_exist, [0, 1, 2]) + """; + var failure = "first argument of [KNN(does_not_exist, [0, 1, 2])] must be [dense_vector, null, text], " + + "found value [does_not_exist] type [keyword]"; + verificationFailure(setUnmappedLoad(query), failure); + } + + public void testFailRateLoad() { + String query = """ + TS k8s + | STATS max(rate(does_not_exist)) + """; + var failure = "first argument of [rate(does_not_exist)] must be [counter_long, counter_integer or counter_double], " + + "found value [does_not_exist] type [keyword]"; + verificationFailure(setUnmappedLoad(query), failure); + } + /* * Limit[1000[INTEGER],false,false] * \_Project[[x{r}#4, does_not_exist_field1{r}#12, y{r}#8, does_not_exist_field2{r}#14]] @@ -3317,6 +3359,17 @@ public void testChangedTimestmapFieldWithRate() { """), "3:13: [rate(network.total_cost)] " + UnresolvedTimestamp.UNRESOLVED_SUFFIX); } + // This test verifies that we do not allow an unmapped @timestamp fields in tbucket. + public void testFailNoUnmappedTimestamp() throws Exception { + String query = (""" + FROM employees + | STATS c = COUNT(*) BY tbucket(1 hour) + """); + var failure = "[tbucket(1 hour)] requires the [@timestamp] field"; + verificationFailure(setUnmappedNullify(query), failure); + verificationFailure(setUnmappedLoad(query), failure); + } + private void verificationFailure(String statement, String expectedFailure) { var e = expectThrows(VerificationException.class, () -> analyzeStatement(statement)); assertThat(e.getMessage(), containsString(expectedFailure)); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 387da6f8f0824..4d0bbc3995745 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -58,6 +58,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -174,6 +175,15 @@ public TestBuilder transportVersion(TransportVersion transportVersion) { public void run() { runGoldenTest(esqlQuery, stages, searchStats, transportVersion, nestedPath); } + + public Optional tryRun() { + try { + run(); + return Optional.empty(); + } catch (Throwable e) { + return Optional.of(e); + } + } } private record Test( @@ -201,7 +211,7 @@ private void doTest() { private List> doTests() throws IOException { var statement = EsqlParser.INSTANCE.createStatement(esqlQuery); var parsedPlan = statement.plan(); - Files.createDirectories(PathUtils.get(basePath.toString(), pathArray(0))); + Files.createDirectories(outputPath()); Files.writeString(outputPath("query.esql"), esqlQuery); var analyzer = new Analyzer( new AnalyzerContext( @@ -303,12 +313,12 @@ private List> doTests() throws IOException { return result; } - // FIXME(gal, NOCOMMIT) Not a fan of this signature - private String[] pathArray(int extraElements) { - var paths = new String[nestedPath.length + 1 + extraElements]; + private Path outputPath(String... extraArrayElements) { + var paths = new String[nestedPath.length + 1 + extraArrayElements.length]; paths[0] = testName; System.arraycopy(nestedPath, 0, paths, 1, nestedPath.length); - return paths; + System.arraycopy(extraArrayElements, 0, paths, 1 + nestedPath.length, extraArrayElements.length); + return PathUtils.get(basePath.toString(), paths); } private enum TestResult { @@ -368,12 +378,6 @@ private Path expectedOutputPath(String stageName) { return outputPath(stageName + ".expected"); } - private Path outputPath(String fileName) { - var paths = pathArray(1); - paths[paths.length - 1] = fileName; - return PathUtils.get(basePath.toString(), paths); - } - private PhysicalPlan localOptimize(PhysicalPlan plan, Configuration conf) { return PlannerUtils.localPlan( EsqlTestUtils.TEST_PLANNER_SETTINGS, diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..338fc3701e44c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[!@timestamp]] + \_EsRelation[sample_data,sample_data_ts_long,no_mapping_sample_data][!@timestamp, client_ip{f}#0, event_duration{f}#1, message{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/query.esql new file mode 100644 index 0000000000000..1e55cfb1096c9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, sample_data_ts_long, no_mapping_sample_data +| KEEP @timestamp diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..338fc3701e44c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[!@timestamp]] + \_EsRelation[sample_data,sample_data_ts_long,no_mapping_sample_data][!@timestamp, client_ip{f}#0, event_duration{f}#1, message{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..75305542ab2b0 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, sample_data_ts_long, no_mapping_sample_data +| KEEP @timestamp diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/analysis.expected new file mode 100644 index 0000000000000..1f2cf5e16ad87 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/analysis.expected @@ -0,0 +1,4 @@ +Project[[!@timestamp, client_ip{f(EsField)}#0, event_duration{f(EsField)}#1, message{f(KeywordEsField)}#2, x{r}#3]] +\_Limit[1000[INTEGER],false,false] + \_Eval[[$$@timestamp$converted_to$double{f(MultiTypeEsField)$}#4 AS x#3]] + \_EsRelation[sample_data,sample_data_ts_long,no_mapping_sample_data][!@timestamp, client_ip{f}#0, event_duration{f}#1, message{f}#2, $$@timestamp$converted_to$double{f$}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/query.esql new file mode 100644 index 0000000000000..b6749814f782a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, sample_data_ts_long, no_mapping_sample_data +| EVAL x = @timestamp :: DOUBLE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/analysis.expected new file mode 100644 index 0000000000000..1f2cf5e16ad87 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/analysis.expected @@ -0,0 +1,4 @@ +Project[[!@timestamp, client_ip{f(EsField)}#0, event_duration{f(EsField)}#1, message{f(KeywordEsField)}#2, x{r}#3]] +\_Limit[1000[INTEGER],false,false] + \_Eval[[$$@timestamp$converted_to$double{f(MultiTypeEsField)$}#4 AS x#3]] + \_EsRelation[sample_data,sample_data_ts_long,no_mapping_sample_data][!@timestamp, client_ip{f}#0, event_duration{f}#1, message{f}#2, $$@timestamp$converted_to$double{f$}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/query.esql new file mode 100644 index 0000000000000..e486841e2f785 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, sample_data_ts_long, no_mapping_sample_data +| EVAL x = @timestamp :: DOUBLE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql index ab8c59e257e6d..ba866b39d02b5 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql @@ -1,3 +1,3 @@ -SET unmapped_fields="nullify"; FROM sample_data, sample_data_ts_long +SET unmapped_fields="nullify"; FROM sample_data, sample_data_ts_long, employees | EVAL ts = @timestamp::STRING | KEEP ts, message, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/analysis.expected new file mode 100644 index 0000000000000..13558bfef2002 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0 AS x#1]] + \_InlineStats[] + \_Aggregate[[emp_no{f(EsField)}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS COUNT(*)#3, emp_no{f(EsField)}#2]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/query.esql new file mode 100644 index 0000000000000..4148af41e94f6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| INLINE STATS COUNT(*) BY emp_no +| EVAL x = does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/analysis.expected new file mode 100644 index 0000000000000..bbfb54572a2cb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/analysis.expected @@ -0,0 +1,6 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[does_not_exist_field{r}#0 AS x#1]] + \_InlineStats[] + \_Aggregate[[emp_no{f(EsField)}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS COUNT(*)#3, emp_no{f(EsField)}#2]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/query.esql new file mode 100644 index 0000000000000..00cb535f496f9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| INLINE STATS COUNT(*) BY emp_no +| EVAL x = does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/analysis.expected new file mode 100644 index 0000000000000..13558bfef2002 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0 AS x#1]] + \_InlineStats[] + \_Aggregate[[emp_no{f(EsField)}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS COUNT(*)#3, emp_no{f(EsField)}#2]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/query.esql new file mode 100644 index 0000000000000..4148af41e94f6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| INLINE STATS COUNT(*) BY emp_no +| EVAL x = does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/analysis.expected new file mode 100644 index 0000000000000..bbfb54572a2cb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/analysis.expected @@ -0,0 +1,6 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[does_not_exist_field{r}#0 AS x#1]] + \_InlineStats[] + \_Aggregate[[emp_no{f(EsField)}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS COUNT(*)#3, emp_no{f(EsField)}#2]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/query.esql new file mode 100644 index 0000000000000..98bbe99592e9a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS COUNT(*) BY emp_no +| EVAL x = salary diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected new file mode 100644 index 0000000000000..f34822d2c1c68 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected @@ -0,0 +1,15 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(_fork{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#55]] + \_FuseScoreEval[_score{r}#2,_fork{r}#54,RRF,null] + \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, _fork{r}#54]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#56, birth_date{f(DateEsField)}#57, emp_no{f(EsField)}#58, first_name{f(KeywordEsField)}#59, gender{f(KeywordEsField)}#60, height{f(EsField)}#61, height.float{f(EsField)}#62, height.half_float{f(EsField)}#63, height.scaled_float{f(EsField)}#64, hire_date{f(DateEsField)}#65, is_rehired{f(EsField)}#66, job_positions{f(KeywordEsField)}#67, languages{f(EsField)}#68, languages.byte{f(EsField)}#69, languages.long{f(EsField)}#70, languages.short{f(EsField)}#71, last_name{f(KeywordEsField)}#72, salary{f(EsField)}#73, salary_change{f(EsField)}#74, salary_change.int{f(EsField)}#75, salary_change.keyword{f(KeywordEsField)}#76, salary_change.long{f(EsField)}#77, still_hired{f(EsField)}#78, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#82, _fork{r}#83]] + | \_Eval[[fork1[KEYWORD] AS _fork#83]] + | \_Filter[TOLONG(does_not_exist{f}#82) > 0[INTEGER]] + | \_EsRelation[employees][avg_worked_seconds{f}#56, birth_date{f}#57, emp_no{f}#58, first_name{f}#59, gender{f}#60, height{f}#61, height.float{f}#62, height.half_float{f}#63, height.scaled_float{f}#64, hire_date{f}#65, is_rehired{f}#66, job_positions{f}#67, languages{f}#68, languages.byte{f}#69, languages.long{f}#70, languages.short{f}#71, last_name{f}#72, salary{f}#73, salary_change{f}#74, salary_change.int{f}#75, salary_change.keyword{f}#76, salary_change.long{f}#77, still_hired{f}#78, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{f}#82] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#84, birth_date{f(DateEsField)}#85, emp_no{f(EsField)}#86, first_name{f(KeywordEsField)}#87, gender{f(KeywordEsField)}#88, height{f(EsField)}#89, height.float{f(EsField)}#90, height.half_float{f(EsField)}#91, height.scaled_float{f(EsField)}#92, hire_date{f(DateEsField)}#93, is_rehired{f(EsField)}#94, job_positions{f(KeywordEsField)}#95, languages{f(EsField)}#96, languages.byte{f(EsField)}#97, languages.long{f(EsField)}#98, languages.short{f(EsField)}#99, last_name{f(KeywordEsField)}#100, salary{f(EsField)}#101, salary_change{f(EsField)}#102, salary_change.int{f(EsField)}#103, salary_change.keyword{f(KeywordEsField)}#104, salary_change.long{f(EsField)}#105, still_hired{f(EsField)}#106, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{r}#107, _fork{r}#83]] + \_Eval[[null[KEYWORD] AS does_not_exist#107]] + \_Eval[[fork2[KEYWORD] AS _fork#83]] + \_Filter[emp_no{f}#86 > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#84, birth_date{f}#85, emp_no{f}#86, first_name{f}#87, gender{f}#88, height{f}#89, height.float{f}#90, height.half_float{f}#91, height.scaled_float{f}#92, hire_date{f}#93, is_rehired{f}#94, job_positions{f}#95, languages{f}#96, languages.byte{f}#97, languages.long{f}#98, languages.short{f}#99, last_name{f}#100, salary{f}#101, salary_change{f}#102, salary_change.int{f}#103, salary_change.keyword{f}#104, salary_change.long{f}#105, still_hired{f}#106, _score{m}#79, _index{m}#80, _id{m}#81] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql new file mode 100644 index 0000000000000..2217f682e64de --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees METADATA _score, _index, _id +| FORK (WHERE does_not_exist::LONG > 0) + (WHERE emp_no > 0) +| FUSE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/analysis.expected new file mode 100644 index 0000000000000..cfa9ace9ad952 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/analysis.expected @@ -0,0 +1,16 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(_fork{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#55]] + \_FuseScoreEval[_score{r}#2,_fork{r}#54,RRF,null] + \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, _fork{r}#54]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#56, birth_date{f(DateEsField)}#57, emp_no{f(EsField)}#58, first_name{f(KeywordEsField)}#59, gender{f(KeywordEsField)}#60, height{f(EsField)}#61, height.float{f(EsField)}#62, height.half_float{f(EsField)}#63, height.scaled_float{f(EsField)}#64, hire_date{f(DateEsField)}#65, is_rehired{f(EsField)}#66, job_positions{f(KeywordEsField)}#67, languages{f(EsField)}#68, languages.byte{f(EsField)}#69, languages.long{f(EsField)}#70, languages.short{f(EsField)}#71, last_name{f(KeywordEsField)}#72, salary{f(EsField)}#73, salary_change{f(EsField)}#74, salary_change.int{f(EsField)}#75, salary_change.keyword{f(KeywordEsField)}#76, salary_change.long{f(EsField)}#77, still_hired{f(EsField)}#78, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{r}#82, _fork{r}#83]] + | \_Eval[[fork1[KEYWORD] AS _fork#83]] + | \_Filter[TOLONG(does_not_exist{r}#82) > 0[INTEGER]] + | \_Eval[[null[NULL] AS does_not_exist#82]] + | \_EsRelation[employees][avg_worked_seconds{f}#56, birth_date{f}#57, emp_no{f}#58, first_name{f}#59, gender{f}#60, height{f}#61, height.float{f}#62, height.half_float{f}#63, height.scaled_float{f}#64, hire_date{f}#65, is_rehired{f}#66, job_positions{f}#67, languages{f}#68, languages.byte{f}#69, languages.long{f}#70, languages.short{f}#71, last_name{f}#72, salary{f}#73, salary_change{f}#74, salary_change.int{f}#75, salary_change.keyword{f}#76, salary_change.long{f}#77, still_hired{f}#78, _score{m}#79, _index{m}#80, _id{m}#81] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#84, birth_date{f(DateEsField)}#85, emp_no{f(EsField)}#86, first_name{f(KeywordEsField)}#87, gender{f(KeywordEsField)}#88, height{f(EsField)}#89, height.float{f(EsField)}#90, height.half_float{f(EsField)}#91, height.scaled_float{f(EsField)}#92, hire_date{f(DateEsField)}#93, is_rehired{f(EsField)}#94, job_positions{f(KeywordEsField)}#95, languages{f(EsField)}#96, languages.byte{f(EsField)}#97, languages.long{f(EsField)}#98, languages.short{f(EsField)}#99, last_name{f(KeywordEsField)}#100, salary{f(EsField)}#101, salary_change{f(EsField)}#102, salary_change.int{f(EsField)}#103, salary_change.keyword{f(KeywordEsField)}#104, salary_change.long{f(EsField)}#105, still_hired{f(EsField)}#106, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{r}#107, _fork{r}#83]] + \_Eval[[null[NULL] AS does_not_exist#107]] + \_Eval[[fork2[KEYWORD] AS _fork#83]] + \_Filter[emp_no{f}#86 > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#84, birth_date{f}#85, emp_no{f}#86, first_name{f}#87, gender{f}#88, height{f}#89, height.float{f}#90, height.half_float{f}#91, height.scaled_float{f}#92, hire_date{f}#93, is_rehired{f}#94, job_positions{f}#95, languages{f}#96, languages.byte{f}#97, languages.long{f}#98, languages.short{f}#99, last_name{f}#100, salary{f}#101, salary_change{f}#102, salary_change.int{f}#103, salary_change.keyword{f}#104, salary_change.long{f}#105, still_hired{f}#106, _score{m}#79, _index{m}#80, _id{m}#81] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/query.esql new file mode 100644 index 0000000000000..53465ff6db0c5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees METADATA _score, _index, _id +| FORK (WHERE does_not_exist::LONG > 0) + (WHERE emp_no > 0) +| FUSE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected new file mode 100644 index 0000000000000..04da9a423e8dc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected @@ -0,0 +1,18 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(x{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS x#55, VALUES(_fork{r}#56,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#57, VALUES(y{r}#58,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#59]] + \_FuseScoreEval[_score{r}#2,_fork{r}#56,LINEAR,null] + \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, x{r}#54, _fork{r}#56, y{r}#58]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#60, birth_date{f(DateEsField)}#61, emp_no{f(EsField)}#62, first_name{f(KeywordEsField)}#63, gender{f(KeywordEsField)}#64, height{f(EsField)}#65, height.float{f(EsField)}#66, height.half_float{f(EsField)}#67, height.scaled_float{f(EsField)}#68, hire_date{f(DateEsField)}#69, is_rehired{f(EsField)}#70, job_positions{f(KeywordEsField)}#71, languages{f(EsField)}#72, languages.byte{f(EsField)}#73, languages.long{f(EsField)}#74, languages.short{f(EsField)}#75, last_name{f(KeywordEsField)}#76, salary{f(EsField)}#77, salary_change{f(EsField)}#78, salary_change.int{f(EsField)}#79, salary_change.keyword{f(KeywordEsField)}#80, salary_change.long{f(EsField)}#81, still_hired{f(EsField)}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#86, x{r}#87, _fork{r}#88, y{r}#89]] + | \_Eval[[null[INTEGER] AS y#89]] + | \_Eval[[fork1[KEYWORD] AS _fork#88]] + | \_Eval[[1[INTEGER] AS x#87]] + | \_Filter[TOLONG(does_not_exist{f}#86) > 0[INTEGER]] + | \_EsRelation[employees][avg_worked_seconds{f}#60, birth_date{f}#61, emp_no{f}#62, first_name{f}#63, gender{f}#64, height{f}#65, height.float{f}#66, height.half_float{f}#67, height.scaled_float{f}#68, hire_date{f}#69, is_rehired{f}#70, job_positions{f}#71, languages{f}#72, languages.byte{f}#73, languages.long{f}#74, languages.short{f}#75, last_name{f}#76, salary{f}#77, salary_change{f}#78, salary_change.int{f}#79, salary_change.keyword{f}#80, salary_change.long{f}#81, still_hired{f}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f}#86] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#90, birth_date{f(DateEsField)}#91, emp_no{f(EsField)}#92, first_name{f(KeywordEsField)}#93, gender{f(KeywordEsField)}#94, height{f(EsField)}#95, height.float{f(EsField)}#96, height.half_float{f(EsField)}#97, height.scaled_float{f(EsField)}#98, hire_date{f(DateEsField)}#99, is_rehired{f(EsField)}#100, job_positions{f(KeywordEsField)}#101, languages{f(EsField)}#102, languages.byte{f(EsField)}#103, languages.long{f(EsField)}#104, languages.short{f(EsField)}#105, last_name{f(KeywordEsField)}#106, salary{f(EsField)}#107, salary_change{f(EsField)}#108, salary_change.int{f(EsField)}#109, salary_change.keyword{f(KeywordEsField)}#110, salary_change.long{f(EsField)}#111, still_hired{f(EsField)}#112, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#113, x{r}#114, _fork{r}#88, y{r}#115]] + \_Eval[[null[KEYWORD] AS does_not_exist#113, null[INTEGER] AS x#114]] + \_Eval[[fork2[KEYWORD] AS _fork#88]] + \_Eval[[2[INTEGER] AS y#115]] + \_Filter[emp_no{f}#92 > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#90, birth_date{f}#91, emp_no{f}#92, first_name{f}#93, gender{f}#94, height{f}#95, height.float{f}#96, height.half_float{f}#97, height.scaled_float{f}#98, hire_date{f}#99, is_rehired{f}#100, job_positions{f}#101, languages{f}#102, languages.byte{f}#103, languages.long{f}#104, languages.short{f}#105, last_name{f}#106, salary{f}#107, salary_change{f}#108, salary_change.int{f}#109, salary_change.keyword{f}#110, salary_change.long{f}#111, still_hired{f}#112, _score{m}#83, _index{m}#84, _id{m}#85] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql new file mode 100644 index 0000000000000..6ca46384903c8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees METADATA _score, _index, _id +| FORK (WHERE does_not_exist::LONG > 0 | EVAL x = 1) + (WHERE emp_no > 0 | EVAL y = 2) +| FUSE LINEAR diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/analysis.expected new file mode 100644 index 0000000000000..2d4aef7657ab1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/analysis.expected @@ -0,0 +1,19 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(x{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS x#55, VALUES(_fork{r}#56,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#57, VALUES(y{r}#58,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#59]] + \_FuseScoreEval[_score{r}#2,_fork{r}#56,LINEAR,null] + \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, x{r}#54, _fork{r}#56, y{r}#58]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#60, birth_date{f(DateEsField)}#61, emp_no{f(EsField)}#62, first_name{f(KeywordEsField)}#63, gender{f(KeywordEsField)}#64, height{f(EsField)}#65, height.float{f(EsField)}#66, height.half_float{f(EsField)}#67, height.scaled_float{f(EsField)}#68, hire_date{f(DateEsField)}#69, is_rehired{f(EsField)}#70, job_positions{f(KeywordEsField)}#71, languages{f(EsField)}#72, languages.byte{f(EsField)}#73, languages.long{f(EsField)}#74, languages.short{f(EsField)}#75, last_name{f(KeywordEsField)}#76, salary{f(EsField)}#77, salary_change{f(EsField)}#78, salary_change.int{f(EsField)}#79, salary_change.keyword{f(KeywordEsField)}#80, salary_change.long{f(EsField)}#81, still_hired{f(EsField)}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#86, x{r}#87, _fork{r}#88, y{r}#89]] + | \_Eval[[null[INTEGER] AS y#89]] + | \_Eval[[fork1[KEYWORD] AS _fork#88]] + | \_Eval[[1[INTEGER] AS x#87]] + | \_Filter[TOLONG(does_not_exist{r}#86) > 0[INTEGER]] + | \_Eval[[null[NULL] AS does_not_exist#86]] + | \_EsRelation[employees][avg_worked_seconds{f}#60, birth_date{f}#61, emp_no{f}#62, first_name{f}#63, gender{f}#64, height{f}#65, height.float{f}#66, height.half_float{f}#67, height.scaled_float{f}#68, hire_date{f}#69, is_rehired{f}#70, job_positions{f}#71, languages{f}#72, languages.byte{f}#73, languages.long{f}#74, languages.short{f}#75, last_name{f}#76, salary{f}#77, salary_change{f}#78, salary_change.int{f}#79, salary_change.keyword{f}#80, salary_change.long{f}#81, still_hired{f}#82, _score{m}#83, _index{m}#84, _id{m}#85] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#90, birth_date{f(DateEsField)}#91, emp_no{f(EsField)}#92, first_name{f(KeywordEsField)}#93, gender{f(KeywordEsField)}#94, height{f(EsField)}#95, height.float{f(EsField)}#96, height.half_float{f(EsField)}#97, height.scaled_float{f(EsField)}#98, hire_date{f(DateEsField)}#99, is_rehired{f(EsField)}#100, job_positions{f(KeywordEsField)}#101, languages{f(EsField)}#102, languages.byte{f(EsField)}#103, languages.long{f(EsField)}#104, languages.short{f(EsField)}#105, last_name{f(KeywordEsField)}#106, salary{f(EsField)}#107, salary_change{f(EsField)}#108, salary_change.int{f(EsField)}#109, salary_change.keyword{f(KeywordEsField)}#110, salary_change.long{f(EsField)}#111, still_hired{f(EsField)}#112, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#113, x{r}#114, _fork{r}#88, y{r}#115]] + \_Eval[[null[NULL] AS does_not_exist#113, null[INTEGER] AS x#114]] + \_Eval[[fork2[KEYWORD] AS _fork#88]] + \_Eval[[2[INTEGER] AS y#115]] + \_Filter[emp_no{f}#92 > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#90, birth_date{f}#91, emp_no{f}#92, first_name{f}#93, gender{f}#94, height{f}#95, height.float{f}#96, height.half_float{f}#97, height.scaled_float{f}#98, hire_date{f}#99, is_rehired{f}#100, job_positions{f}#101, languages{f}#102, languages.byte{f}#103, languages.long{f}#104, languages.short{f}#105, last_name{f}#106, salary{f}#107, salary_change{f}#108, salary_change.int{f}#109, salary_change.keyword{f}#110, salary_change.long{f}#111, still_hired{f}#112, _score{m}#83, _index{m}#84, _id{m}#85] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/query.esql new file mode 100644 index 0000000000000..b4201b56e3cf8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees METADATA _score, _index, _id +| FORK (WHERE does_not_exist::LONG > 0 | EVAL x = 1) + (WHERE emp_no > 0 | EVAL y = 2) +| FUSE LINEAR diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected new file mode 100644 index 0000000000000..bc41c8f49b9f2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected @@ -0,0 +1,16 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(x{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS x#55, VALUES(_fork{r}#56,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#57, VALUES(y{r}#58,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#59]] + \_FuseScoreEval[_score{r}#2,_fork{r}#56,RRF,null] + \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, x{r}#54, _fork{r}#56, y{r}#58]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#60, birth_date{f(DateEsField)}#61, emp_no{f(EsField)}#62, first_name{f(KeywordEsField)}#63, gender{f(KeywordEsField)}#64, height{f(EsField)}#65, height.float{f(EsField)}#66, height.half_float{f(EsField)}#67, height.scaled_float{f(EsField)}#68, hire_date{f(DateEsField)}#69, is_rehired{f(EsField)}#70, job_positions{f(KeywordEsField)}#71, languages{f(EsField)}#72, languages.byte{f(EsField)}#73, languages.long{f(EsField)}#74, languages.short{f(EsField)}#75, last_name{f(KeywordEsField)}#76, salary{f(EsField)}#77, salary_change{f(EsField)}#78, salary_change.int{f(EsField)}#79, salary_change.keyword{f(KeywordEsField)}#80, salary_change.long{f(EsField)}#81, still_hired{f(EsField)}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#86, x{r}#87, _fork{r}#88, y{r}#89]] + | \_Eval[[null[INTEGER] AS y#89]] + | \_Eval[[fork1[KEYWORD] AS _fork#88]] + | \_Eval[[TODOUBLE(does_not_exist{f}#86) + 1[INTEGER] AS x#87]] + | \_EsRelation[employees][avg_worked_seconds{f}#60, birth_date{f}#61, emp_no{f}#62, first_name{f}#63, gender{f}#64, height{f}#65, height.float{f}#66, height.half_float{f}#67, height.scaled_float{f}#68, hire_date{f}#69, is_rehired{f}#70, job_positions{f}#71, languages{f}#72, languages.byte{f}#73, languages.long{f}#74, languages.short{f}#75, last_name{f}#76, salary{f}#77, salary_change{f}#78, salary_change.int{f}#79, salary_change.keyword{f}#80, salary_change.long{f}#81, still_hired{f}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f}#86] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#90, birth_date{f(DateEsField)}#91, emp_no{f(EsField)}#92, first_name{f(KeywordEsField)}#93, gender{f(KeywordEsField)}#94, height{f(EsField)}#95, height.float{f(EsField)}#96, height.half_float{f(EsField)}#97, height.scaled_float{f(EsField)}#98, hire_date{f(DateEsField)}#99, is_rehired{f(EsField)}#100, job_positions{f(KeywordEsField)}#101, languages{f(EsField)}#102, languages.byte{f(EsField)}#103, languages.long{f(EsField)}#104, languages.short{f(EsField)}#105, last_name{f(KeywordEsField)}#106, salary{f(EsField)}#107, salary_change{f(EsField)}#108, salary_change.int{f(EsField)}#109, salary_change.keyword{f(KeywordEsField)}#110, salary_change.long{f(EsField)}#111, still_hired{f(EsField)}#112, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#113, x{r}#114, _fork{r}#88, y{r}#115]] + \_Eval[[null[KEYWORD] AS does_not_exist#113, null[DOUBLE] AS x#114]] + \_Eval[[fork2[KEYWORD] AS _fork#88]] + \_Eval[[emp_no{f}#92 + 1[INTEGER] AS y#115]] + \_EsRelation[employees][avg_worked_seconds{f}#90, birth_date{f}#91, emp_no{f}#92, first_name{f}#93, gender{f}#94, height{f}#95, height.float{f}#96, height.half_float{f}#97, height.scaled_float{f}#98, hire_date{f}#99, is_rehired{f}#100, job_positions{f}#101, languages{f}#102, languages.byte{f}#103, languages.long{f}#104, languages.short{f}#105, last_name{f}#106, salary{f}#107, salary_change{f}#108, salary_change.int{f}#109, salary_change.keyword{f}#110, salary_change.long{f}#111, still_hired{f}#112, _score{m}#83, _index{m}#84, _id{m}#85] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql new file mode 100644 index 0000000000000..28caa1c3f1e98 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees METADATA _score, _index, _id +| FORK (EVAL x = does_not_exist::DOUBLE + 1) + (EVAL y = emp_no + 1) +| FUSE RRF diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/analysis.expected new file mode 100644 index 0000000000000..7c2ca4cbcfc17 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/analysis.expected @@ -0,0 +1,17 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(x{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS x#55, VALUES(_fork{r}#56,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#57, VALUES(y{r}#58,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#59]] + \_FuseScoreEval[_score{r}#2,_fork{r}#56,RRF,null] + \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, x{r}#54, _fork{r}#56, y{r}#58]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#60, birth_date{f(DateEsField)}#61, emp_no{f(EsField)}#62, first_name{f(KeywordEsField)}#63, gender{f(KeywordEsField)}#64, height{f(EsField)}#65, height.float{f(EsField)}#66, height.half_float{f(EsField)}#67, height.scaled_float{f(EsField)}#68, hire_date{f(DateEsField)}#69, is_rehired{f(EsField)}#70, job_positions{f(KeywordEsField)}#71, languages{f(EsField)}#72, languages.byte{f(EsField)}#73, languages.long{f(EsField)}#74, languages.short{f(EsField)}#75, last_name{f(KeywordEsField)}#76, salary{f(EsField)}#77, salary_change{f(EsField)}#78, salary_change.int{f(EsField)}#79, salary_change.keyword{f(KeywordEsField)}#80, salary_change.long{f(EsField)}#81, still_hired{f(EsField)}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#86, x{r}#87, _fork{r}#88, y{r}#89]] + | \_Eval[[null[INTEGER] AS y#89]] + | \_Eval[[fork1[KEYWORD] AS _fork#88]] + | \_Eval[[TODOUBLE(does_not_exist{r}#86) + 1[INTEGER] AS x#87]] + | \_Eval[[null[NULL] AS does_not_exist#86]] + | \_EsRelation[employees][avg_worked_seconds{f}#60, birth_date{f}#61, emp_no{f}#62, first_name{f}#63, gender{f}#64, height{f}#65, height.float{f}#66, height.half_float{f}#67, height.scaled_float{f}#68, hire_date{f}#69, is_rehired{f}#70, job_positions{f}#71, languages{f}#72, languages.byte{f}#73, languages.long{f}#74, languages.short{f}#75, last_name{f}#76, salary{f}#77, salary_change{f}#78, salary_change.int{f}#79, salary_change.keyword{f}#80, salary_change.long{f}#81, still_hired{f}#82, _score{m}#83, _index{m}#84, _id{m}#85] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#90, birth_date{f(DateEsField)}#91, emp_no{f(EsField)}#92, first_name{f(KeywordEsField)}#93, gender{f(KeywordEsField)}#94, height{f(EsField)}#95, height.float{f(EsField)}#96, height.half_float{f(EsField)}#97, height.scaled_float{f(EsField)}#98, hire_date{f(DateEsField)}#99, is_rehired{f(EsField)}#100, job_positions{f(KeywordEsField)}#101, languages{f(EsField)}#102, languages.byte{f(EsField)}#103, languages.long{f(EsField)}#104, languages.short{f(EsField)}#105, last_name{f(KeywordEsField)}#106, salary{f(EsField)}#107, salary_change{f(EsField)}#108, salary_change.int{f(EsField)}#109, salary_change.keyword{f(KeywordEsField)}#110, salary_change.long{f(EsField)}#111, still_hired{f(EsField)}#112, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#113, x{r}#114, _fork{r}#88, y{r}#115]] + \_Eval[[null[NULL] AS does_not_exist#113, null[DOUBLE] AS x#114]] + \_Eval[[fork2[KEYWORD] AS _fork#88]] + \_Eval[[emp_no{f}#92 + 1[INTEGER] AS y#115]] + \_EsRelation[employees][avg_worked_seconds{f}#90, birth_date{f}#91, emp_no{f}#92, first_name{f}#93, gender{f}#94, height{f}#95, height.float{f}#96, height.half_float{f}#97, height.scaled_float{f}#98, hire_date{f}#99, is_rehired{f}#100, job_positions{f}#101, languages{f}#102, languages.byte{f}#103, languages.long{f}#104, languages.short{f}#105, last_name{f}#106, salary{f}#107, salary_change{f}#108, salary_change.int{f}#109, salary_change.keyword{f}#110, salary_change.long{f}#111, still_hired{f}#112, _score{m}#83, _index{m}#84, _id{m}#85] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/query.esql new file mode 100644 index 0000000000000..b4413e66d0853 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees METADATA _score, _index, _id +| FORK (EVAL x = does_not_exist::DOUBLE + 1) + (EVAL y = emp_no + 1) +| FUSE RRF diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected index d21ff127af792..2dea9af44b3d1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected @@ -1,3 +1,4 @@ Limit[1000[INTEGER],false,false] -\_Project[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0]] - \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#0] \ No newline at end of file +\_Project[[x{r}#0]] + \_Eval[[TOVERSION(does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#1) AS x#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/query.esql index 85b4cb1847fc2..4508523015814 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/query.esql @@ -1,2 +1,3 @@ SET unmapped_fields="load"; FROM employees -| KEEP does_not_exist_field +| eval x = does_not_exist_field :: version +| keep x diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/analysis.expected index 4cc092c3f4aee..25f14d02025c3 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/analysis.expected @@ -1,4 +1,5 @@ Limit[1000[INTEGER],false,false] -\_Project[[does_not_exist_field{r}#0]] - \_Eval[[null[NULL] AS does_not_exist_field#0]] - \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file +\_Project[[x{r}#0]] + \_Eval[[TOVERSION(does_not_exist_field{r}#1) AS x#0]] + \_Eval[[null[NULL] AS does_not_exist_field#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/query.esql index aa0cb37ad9b24..696229a0c3317 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/query.esql @@ -1,2 +1,3 @@ SET unmapped_fields="nullify"; FROM employees -| KEEP does_not_exist_field +| eval x = does_not_exist_field :: version +| keep x diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql index 4297a1b213923..45bedb56b16b8 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql @@ -1,3 +1,3 @@ SET unmapped_fields="load"; FROM employees -| EVAL language_code = does_not_exist::INTEGER +| EVAL language_code = does_not_exist :: INTEGER | LOOKUP JOIN languages_lookup ON language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/query.esql index e0f372f5ca05b..a17cbe97c2008 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/query.esql @@ -1,3 +1,3 @@ SET unmapped_fields="nullify"; FROM employees -| EVAL language_code = does_not_exist::INTEGER +| EVAL language_code = does_not_exist :: INTEGER | LOOKUP JOIN languages_lookup ON language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/analysis.expected new file mode 100644 index 0000000000000..4074128abfe69 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[message{f(PotentiallyUnmappedKeywordEsField)}#0]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#1, client_ip{f}#2, event_duration{f}#3, message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/query.esql new file mode 100644 index 0000000000000..3b89545a17fb7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, no_mapping_sample_data +| KEEP message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/analysis.expected new file mode 100644 index 0000000000000..b2a87f783ec41 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[message{f(KeywordEsField)}#0]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#1, client_ip{f}#2, event_duration{f}#3, message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/query.esql new file mode 100644 index 0000000000000..9ab256bac0ccc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, no_mapping_sample_data +| KEEP message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/analysis.expected new file mode 100644 index 0000000000000..9ec2b3b4a4afd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TOLONG(message{f(PotentiallyUnmappedKeywordEsField)}#0) AS x#1]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/query.esql new file mode 100644 index 0000000000000..5f15147e4ed84 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, no_mapping_sample_data +| EVAL x = message :: LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/analysis.expected new file mode 100644 index 0000000000000..199057917fbe8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TOLONG(message{f(KeywordEsField)}#0) AS x#1]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/query.esql new file mode 100644 index 0000000000000..46601c5b712ed --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, no_mapping_sample_data +| EVAL x = message :: LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/analysis.expected new file mode 100644 index 0000000000000..812e7c610bd25 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[!event_duration]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#0, client_ip{f}#1, event_duration{f}#2, message{f}#3] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/query.esql new file mode 100644 index 0000000000000..2d32247edd0a4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, no_mapping_sample_data +| KEEP event_duration diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/analysis.expected new file mode 100644 index 0000000000000..c417694e5f80d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[event_duration{f(EsField)}#0]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#1, client_ip{f}#2, event_duration{f}#0, message{f}#3] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/query.esql new file mode 100644 index 0000000000000..dac9f41556304 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, no_mapping_sample_data +| KEEP event_duration diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/analysis.expected new file mode 100644 index 0000000000000..18306fbb2a3b6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/analysis.expected @@ -0,0 +1,4 @@ +Project[[@timestamp{f(DateEsField)}#0, client_ip{f(EsField)}#1, !event_duration, message{f(KeywordEsField)}#2, x{r}#3]] +\_Limit[1000[INTEGER],false,false] + \_Eval[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#4 AS x#3]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#0, client_ip{f}#1, !event_duration, message{f}#2, $$event_duration$converted_to$double{f$}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql new file mode 100644 index 0000000000000..75ac5ca4e241d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, no_mapping_sample_data +| EVAL x = event_duration :: DOUBLE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/analysis.expected new file mode 100644 index 0000000000000..bfa31bd940d18 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(event_duration{f(EsField)}#0) AS x#1]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#0, message{f}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/query.esql new file mode 100644 index 0000000000000..59b35e88e844b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, no_mapping_sample_data +| EVAL x = event_duration :: DOUBLE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/load/query.esql new file mode 100644 index 0000000000000..7c1e28505d1fa --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; SET unmapped_fields="load"; FROM employees, (FROM languages | KEEP emp_no) +| KEEP emp_no, language_code +| WHERE emp_no > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/nullify/query.esql new file mode 100644 index 0000000000000..62dc68de394b6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; SET unmapped_fields="load"; FROM employees, (FROM languages | KEEP emp_no) +| KEEP emp_no, language_code +| WHERE emp_no > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected index b4452dd003c30..cc9006fedeefc 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected @@ -1,11 +1,13 @@ Limit[1000[INTEGER],false,false] \_Project[[emp_no{r}#0, language_code{r}#1, does_not_exist{r}#2]] \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, language_code{r}#1, does_not_exist{r}#2]] - |_Project[[avg_worked_seconds{f(EsField)}#25, birth_date{f(DateEsField)}#26, emp_no{f(EsField)}#27, first_name{f(KeywordEsField)}#28, gender{f(KeywordEsField)}#29, height{f(EsField)}#30, height.float{f(EsField)}#31, height.half_float{f(EsField)}#32, height.scaled_float{f(EsField)}#33, hire_date{f(DateEsField)}#34, is_rehired{f(EsField)}#35, job_positions{f(KeywordEsField)}#36, languages{f(EsField)}#37, languages.byte{f(EsField)}#38, languages.long{f(EsField)}#39, languages.short{f(EsField)}#40, last_name{f(KeywordEsField)}#41, salary{f(EsField)}#42, salary_change{f(EsField)}#43, salary_change.int{f(EsField)}#44, salary_change.keyword{f(KeywordEsField)}#45, salary_change.long{f(EsField)}#46, still_hired{f(EsField)}#47, language_code{r}#48, does_not_exist{r}#49]] - | \_Eval[[null[INTEGER] AS language_code#48, null[KEYWORD] AS does_not_exist#49]] - | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] - \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f(EsField)}#73, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74]] - \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] - \_Subquery[] - \_Project[[language_code{f(EsField)}#73, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74]] - \_EsRelation[languages][language_code{f}#73, language_name{f}#75, does_not_exist{f}#74] \ No newline at end of file + |_Project[[avg_worked_seconds{f(EsField)}#25, birth_date{f(DateEsField)}#26, emp_no{f(EsField)}#27, first_name{f(KeywordEsField)}#28, gender{f(KeywordEsField)}#29, height{f(EsField)}#30, height.float{f(EsField)}#31, height.half_float{f(EsField)}#32, height.scaled_float{f(EsField)}#33, hire_date{f(DateEsField)}#34, is_rehired{f(EsField)}#35, job_positions{f(KeywordEsField)}#36, languages{f(EsField)}#37, languages.byte{f(EsField)}#38, languages.long{f(EsField)}#39, languages.short{f(EsField)}#40, last_name{f(KeywordEsField)}#41, salary{f(EsField)}#42, salary_change{f(EsField)}#43, salary_change.int{f(EsField)}#44, salary_change.keyword{f(KeywordEsField)}#45, salary_change.long{f(EsField)}#46, still_hired{f(EsField)}#47, language_code{r}#48, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#49]] + | \_Eval[[null[INTEGER] AS language_code#48]] + | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, does_not_exist{f}#49] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f(EsField)}#73, does_not_exist{r}#74]] + \_Eval[[null[KEYWORD] AS does_not_exist#74]] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f(EsField)}#73]] + \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] + \_Subquery[] + \_Project[[language_code{f(EsField)}#73]] + \_EsRelation[languages][language_code{f}#73, language_name{f}#75, does_not_exist{f}#76] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql index de7a454b426f7..1b76ece4d7ba5 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql @@ -1,2 +1,2 @@ -SET unmapped_fields="load"; FROM employees, (FROM languages | KEEP language_code, does_not_exist) +SET unmapped_fields="load"; FROM employees, (FROM languages | KEEP language_code) | KEEP emp_no, language_code, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected index 6efd06cbbc7de..5d191d8cee373 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected @@ -5,8 +5,10 @@ Limit[1000[INTEGER],false,false] | \_Eval[[null[INTEGER] AS language_code#48, null[NULL] AS does_not_exist#49]] | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f(EsField)}#73, does_not_exist{r}#74]] - \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] - \_Subquery[] - \_Project[[language_code{f(EsField)}#73, does_not_exist{r}#74]] - \_Eval[[null[NULL] AS does_not_exist#74]] - \_EsRelation[languages][language_code{f}#73, language_name{f}#75] \ No newline at end of file + \_Eval[[null[NULL] AS does_not_exist#74]] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f(EsField)}#73]] + \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] + \_Subquery[] + \_Project[[language_code{f(EsField)}#73]] + \_Eval[[null[NULL] AS does_not_exist#75]] + \_EsRelation[languages][language_code{f}#73, language_name{f}#76] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/query.esql index 8aa4d0fd116ce..b1c83359017cb 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/query.esql @@ -1,2 +1,2 @@ -SET unmapped_fields="nullify"; FROM employees, (FROM languages | KEEP language_code, does_not_exist) +SET unmapped_fields="nullify"; FROM employees, (FROM languages | KEEP language_code) | KEEP emp_no, language_code, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/load/query.esql new file mode 100644 index 0000000000000..f2fed1cf47861 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS c = COUNT(*) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/nullify/query.esql new file mode 100644 index 0000000000000..8f4b99c0e762b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS c = COUNT(*) BY tbucket(1 hour) diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/apps.csv b/x-pack/plugin/sql/qa/server/src/main/resources/apps.csv index 9bd4123424f02..7fefd7bfb316f 100644 --- a/x-pack/plugin/sql/qa/server/src/main/resources/apps.csv +++ b/x-pack/plugin/sql/qa/server/src/main/resources/apps.csv @@ -1,4 +1,4 @@ -id,version,name +id,version2,name 1,1,aaaaa 2,2.1,bbbbb 3,2.3.4,ccccc From 9aaca405d06fc297250e537a0796151026d58f0a Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Fri, 6 Feb 2026 20:13:56 +0200 Subject: [PATCH 024/137] Added some nullify tests, fix CsvTests bug --- .idea/inspectionProfiles/Project_Default.xml | 15 --- .../xpack/esql/qa/rest/EsqlSpecTestCase.java | 3 + .../main/resources/unmapped-nullify.csv-spec | 106 ++++++++++++++++++ .../elasticsearch/xpack/esql/CsvTests.java | 27 ++++- .../analysis/AnalyzerUnmappedGoldenTests.java | 25 ++++- .../TestPhysicalOperationProviders.java | 42 +++++-- 6 files changed, 181 insertions(+), 37 deletions(-) delete mode 100644 .idea/inspectionProfiles/Project_Default.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index c99248332b8a9..0000000000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - \ No newline at end of file diff --git a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java index fdddd59d84255..a6d5dfa6fe30b 100644 --- a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java +++ b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java @@ -371,6 +371,9 @@ protected void doTest() throws Throwable { } protected final void doTest(String query) throws Throwable { + if (query.toUpperCase().startsWith("SET") == false) { + query = "SET unmapped_fields=\"load\"; " + query; + } RequestObjectBuilder builder = new RequestObjectBuilder(randomFrom(XContentType.values())); if (query.toUpperCase(Locale.ROOT).contains("LOOKUP_\uD83D\uDC14")) { diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec index b2644559ad26a..48f0e0db265fa 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec @@ -12,6 +12,22 @@ null null ; +partialMappingUnmappedFromSource +required_capability: optional_fields_nullify_tech_preview + +SET unmapped_fields="nullify"\; +FROM partial_mapping_sample_data +| KEEP @timestamp, unmapped_message +| SORT @timestamp DESC +| LIMIT 3 +; + +@timestamp:date | unmapped_message:null +2024-10-23T13:55:01.543Z | null +2024-10-23T13:53:55.832Z | null +2024-10-23T13:52:55.015Z | null +; + keepStar required_capability: optional_fields_nullify_tech_preview @@ -482,3 +498,93 @@ ROW x = 1 x:integer |does_not_exist:null |y:keyword | language_name:keyword 1 |null |null |null ; + +partiallyUnmappedKeywordMultiIndex +required_capability: optional_fields_nullify_tech_preview +required_capability: index_metadata_field + +SET unmapped_fields="nullify"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| KEEP _index, @timestamp, message +| SORT _index, @timestamp DESC +; + +_index:keyword | @timestamp:date | message:keyword +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +sample_data | 2023-10-23T13:55:01.543Z | Connected to 10.1.0.1 +sample_data | 2023-10-23T13:53:55.832Z | Connection error +sample_data | 2023-10-23T13:52:55.015Z | Connection error +sample_data | 2023-10-23T13:51:54.732Z | Connection error +sample_data | 2023-10-23T13:33:34.937Z | Disconnected +sample_data | 2023-10-23T12:27:28.948Z | Connected to 10.1.0.2 +sample_data | 2023-10-23T12:15:03.360Z | Connected to 10.1.0.3 +; + +partiallyUnmappedNonKeywordMultiIndexCast +required_capability: optional_fields_nullify_tech_preview +required_capability: index_metadata_field + +SET unmapped_fields="nullify"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL duration = event_duration::DOUBLE +| KEEP _index, @timestamp, duration +| SORT _index, @timestamp DESC +; + +_index:keyword | @timestamp:date | duration:double +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +sample_data | 2023-10-23T13:55:01.543Z | 1756467.0 +sample_data | 2023-10-23T13:53:55.832Z | 5033755.0 +sample_data | 2023-10-23T13:52:55.015Z | 8268153.0 +sample_data | 2023-10-23T13:51:54.732Z | 725448.0 +sample_data | 2023-10-23T13:33:34.937Z | 1232382.0 +sample_data | 2023-10-23T12:27:28.948Z | 2764889.0 +sample_data | 2023-10-23T12:15:03.360Z | 3450233.0 +; + +partiallyUnmappedMixedTypesMultiIndexCast +required_capability: optional_fields_nullify_tech_preview +required_capability: index_metadata_field + +SET unmapped_fields="nullify"\; +FROM sample_data, logs, no_mapping_sample_data METADATA _index +| EVAL msg = message::KEYWORD +| KEEP _index, @timestamp, msg +| SORT _index, @timestamp DESC +; + +_index:keyword | @timestamp:date | msg:keyword +logs | 2023-10-23T13:57:01.544Z | Running cats (cycle 3) +logs | 2023-10-23T13:56:01.544Z | Running cats (cycle 2) +logs | 2023-10-23T13:56:01.543Z | No response +logs | 2023-10-23T13:55:01.546Z | More java stuff +logs | 2023-10-23T13:55:01.545Z | Doing java stuff for 192.168.86.038 +logs | 2023-10-23T13:55:01.544Z | Running cats (cycle 1) +logs | 2023-10-23T13:55:01.543Z | Pinging 192.168.86.046 +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +sample_data | 2023-10-23T13:55:01.543Z | Connected to 10.1.0.1 +sample_data | 2023-10-23T13:53:55.832Z | Connection error +sample_data | 2023-10-23T13:52:55.015Z | Connection error +sample_data | 2023-10-23T13:51:54.732Z | Connection error +sample_data | 2023-10-23T13:33:34.937Z | Disconnected +sample_data | 2023-10-23T12:27:28.948Z | Connected to 10.1.0.2 +sample_data | 2023-10-23T12:15:03.360Z | Connected to 10.1.0.3 +; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java index bb3eb9518bd29..521f794233f25 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java @@ -720,19 +720,35 @@ public static Map testDa private static TestPhysicalOperationProviders testOperationProviders( FoldContext foldCtx, - Map allDatasets + Map allDatasets, + UnmappedResolution unmappedResolution ) throws Exception { var indexPages = new ArrayList(); for (CsvTestsDataLoader.MultiIndexTestDataset datasets : allDatasets.values()) { for (CsvTestsDataLoader.TestDataset dataset : datasets.datasets()) { var testData = loadPageFromCsv(CsvTests.class.getResource("/data/" + dataset.dataFileName()), dataset.typeMapping()); - Set mappedFields = loadMapping(dataset.mappingFileName()).keySet(); + Set mappedFields = flattenMappingNames(loadMapping(dataset.mappingFileName())); indexPages.add( new TestPhysicalOperationProviders.IndexPage(dataset.indexName(), testData.v1(), testData.v2(), mappedFields) ); } } - return TestPhysicalOperationProviders.create(foldCtx, indexPages); + return TestPhysicalOperationProviders.create(foldCtx, indexPages, unmappedResolution); + } + + private static Set flattenMappingNames(Map mapping) { + Set result = new HashSet<>(); + for (Map.Entry entry : mapping.entrySet()) { + collectFieldNames(entry.getKey(), entry.getValue(), result); + } + return result; + } + + private static void collectFieldNames(String prefix, EsField field, Set result) { + result.add(prefix); + for (Map.Entry sub : field.getProperties().entrySet()) { + collectFieldNames(prefix + "." + sub.getKey(), sub.getValue(), result); + } } private ActualResults executePlan(BigArrays bigArrays) throws Exception { @@ -748,7 +764,8 @@ private ActualResults executePlan(BigArrays bigArrays) throws Exception { var testDatasets = testDatasets(plan); // Specifically use the newest transport version; the csv tests correspond to a single node cluster on the current version. TransportVersion minimumVersion = TransportVersion.current(); - LogicalPlan analyzed = analyzedPlan(plan, statement.setting(UNMAPPED_FIELDS), configuration, testDatasets, minimumVersion); + var unmappedResolution = statement.setting(UNMAPPED_FIELDS); + LogicalPlan analyzed = analyzedPlan(plan, unmappedResolution, configuration, testDatasets, minimumVersion); FoldContext foldCtx = FoldContext.small(); EsqlSession session = new EsqlSession( @@ -767,7 +784,7 @@ private ActualResults executePlan(BigArrays bigArrays) throws Exception { null, EsqlTestUtils.MOCK_TRANSPORT_ACTION_SERVICES ); - TestPhysicalOperationProviders physicalOperationProviders = testOperationProviders(foldCtx, testDatasets); + TestPhysicalOperationProviders physicalOperationProviders = testOperationProviders(foldCtx, testDatasets, unmappedResolution); PlainActionFuture listener = new PlainActionFuture<>(); var logicalPlanPreOptimizer = new LogicalPlanPreOptimizer( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java index 8aad5cdec6b1c..7db188b55c045 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -429,9 +429,8 @@ public void testMappedToNonKeywordInOneIndexOnly() throws Exception { """); } - @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/pull/141912") public void testMappedToNonKeywordInOneIndexOnlyCast() throws Exception { - runTests(""" + runTestsLoadOnly(""" FROM sample_data, no_mapping_sample_data | EVAL x = event_duration :: DOUBLE """); @@ -460,8 +459,8 @@ private static String setUnmappedLoad(String query) { } private void runTests(String query) { - var nullifyException = runTestsNullifyOnly(query); - var loadException = runTestsLoadOnly(query); + var nullifyException = tryRunTestsNullifyOnly(query); + var loadException = tryRunTestsLoadOnly(query); if (nullifyException.isPresent() && loadException.isPresent()) { throw new AssertionError("Both nullify and load modes failed", nullifyException.get()); } else if (nullifyException.isPresent()) { @@ -471,13 +470,27 @@ private void runTests(String query) { } } - private Optional runTestsNullifyOnly(String query) { + private void runTestsNullifyOnly(String query) { + var nullifyException = tryRunTestsNullifyOnly(query); + if (nullifyException.isPresent()) { + throw new RuntimeException("Nullify mode failed", nullifyException.get()); + } + } + + private Optional tryRunTestsNullifyOnly(String query) { return EsqlCapabilities.Cap.OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW.isEnabled() ? builder(setUnmappedNullify(query)).nestedPath("nullify").stages(STAGES).tryRun() : Optional.empty(); } - private Optional runTestsLoadOnly(String query) { + private void runTestsLoadOnly(String query) { + var loadException = tryRunTestsLoadOnly(query); + if (loadException.isPresent()) { + throw new RuntimeException("Load mode failed", loadException.get()); + } + } + + private Optional tryRunTestsLoadOnly(String query) { return EsqlCapabilities.Cap.OPTIONAL_FIELDS.isEnabled() ? builder(setUnmappedLoad(query)).nestedPath("load").stages(STAGES).tryRun() : Optional.empty(); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java index 9d6815b74af5e..fc9e383e95021 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java @@ -43,6 +43,7 @@ import org.elasticsearch.plugins.scanners.StablePluginsRegistry; import org.elasticsearch.xpack.cluster.routing.allocation.mapper.DataTierFieldMapper; import org.elasticsearch.xpack.esql.EsqlIllegalArgumentException; +import org.elasticsearch.xpack.esql.analysis.UnmappedResolution; import org.elasticsearch.xpack.esql.core.expression.Attribute; import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; import org.elasticsearch.xpack.esql.core.expression.FoldContext; @@ -77,14 +78,25 @@ public class TestPhysicalOperationProviders extends AbstractPhysicalOperationProviders { private final List indexPages; + private final UnmappedResolution unmappedResolution; - private TestPhysicalOperationProviders(FoldContext foldContext, List indexPages, AnalysisRegistry analysisRegistry) { + private TestPhysicalOperationProviders( + FoldContext foldContext, + List indexPages, + UnmappedResolution unmappedResolution, + AnalysisRegistry analysisRegistry + ) { super(foldContext, analysisRegistry); this.indexPages = indexPages; + this.unmappedResolution = unmappedResolution; } - public static TestPhysicalOperationProviders create(FoldContext foldContext, List indexPages) throws IOException { - return new TestPhysicalOperationProviders(foldContext, indexPages, createAnalysisRegistry()); + public static TestPhysicalOperationProviders create( + FoldContext foldContext, + List indexPages, + UnmappedResolution unmappedResolution + ) throws IOException { + return new TestPhysicalOperationProviders(foldContext, indexPages, unmappedResolution, createAnalysisRegistry()); } public record IndexPage(String index, Page page, List columnNames, Set mappedFields) { @@ -92,6 +104,7 @@ Optional columnIndex(String columnName) { var result = IntStream.range(0, columnNames.size()).filter(i -> columnNames.get(i).equals(columnName)).findFirst(); return result.isPresent() ? Optional.of(result.getAsInt()) : Optional.empty(); } + } private static AnalysisRegistry createAnalysisRegistry() throws IOException { @@ -283,11 +296,16 @@ private BiFunction getBlockExtraction(DriverCo } } return (indexDoc, blockCopier) -> switch (extractBlockForSingleDoc(indexDoc, attribute.name(), blockCopier)) { - case BlockResultMissing missing -> throw new EsqlIllegalArgumentException( - "Cannot find column named [{}] in {}", - missing.columnName, - missing.columnNames - ); + case BlockResultMissing missing -> { + if (unmappedResolution == UnmappedResolution.NULLIFY) { + yield getNullsBlock(indexDoc); + } + throw new EsqlIllegalArgumentException( + "Cannot find column named [{}] in {}", + missing.columnName, + missing.columnNames + ); + } case BlockResultSuccess success -> success.block; }; } @@ -338,9 +356,11 @@ private BlockResult extractBlockForSingleDoc(DocBlock docBlock, String columnNam docBlock.blockFactory() .newConstantBytesRefBlockWith(new BytesRef("data_content"), blockCopier.docIndices.getPositionCount()) ); - default -> indexPage.columnIndex(columnName) - .map(columnIndex -> new BlockResultSuccess(blockCopier.copyBlock(indexPage.page.getBlock(columnIndex)))) - .orElseGet(() -> new BlockResultMissing(columnName, indexPage.columnNames())); + default -> unmappedResolution == UnmappedResolution.NULLIFY && indexPage.mappedFields().contains(columnName) == false + ? new BlockResultMissing(columnName, indexPage.columnNames()) + : indexPage.columnIndex(columnName) + .map(columnIndex -> new BlockResultSuccess(blockCopier.copyBlock(indexPage.page.getBlock(columnIndex)))) + .orElseGet(() -> new BlockResultMissing(columnName, indexPage.columnNames())); }; } From 7a3b810c7ca25aab38df7d96bd47484971d3f86e Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Fri, 6 Feb 2026 18:21:57 +0000 Subject: [PATCH 025/137] [CI] Auto commit changes from spotless --- .../xpack/esql/planner/TestPhysicalOperationProviders.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java index fc9e383e95021..da247eb443ecc 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java @@ -300,11 +300,7 @@ private BiFunction getBlockExtraction(DriverCo if (unmappedResolution == UnmappedResolution.NULLIFY) { yield getNullsBlock(indexDoc); } - throw new EsqlIllegalArgumentException( - "Cannot find column named [{}] in {}", - missing.columnName, - missing.columnNames - ); + throw new EsqlIllegalArgumentException("Cannot find column named [{}] in {}", missing.columnName, missing.columnNames); } case BlockResultSuccess success -> success.block; }; From c33a2c634d38cedf11d1d66785402f1e6e40fae3 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 9 Feb 2026 15:49:57 +0200 Subject: [PATCH 026/137] Prevent filter pushdown on potentially unmapped fields PotentiallyUnmappedKeywordEsField (used for fields loaded from _source when unmapped_fields="load") had isAggregatable=true, which caused isPushableFieldAttribute to short-circuit past the SearchStats check and push filters down to Lucene. On shards where the field is not indexed, the Lucene query returns no results instead of letting the compute engine evaluate the filter on _source-loaded values. Guard isPushableFieldAttribute against PotentiallyUnmappedKeywordEsField so these fields are always filtered in the compute engine. Co-authored-by: Cursor --- .../src/main/resources/unmapped-load.csv-spec | 62 ++++++++++++------- .../local/LucenePushdownPredicates.java | 6 +- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index d0b808a601540..0a3990c33c1fa 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -385,20 +385,20 @@ FROM partial_mapping_sample_data, sample_data METADATA _index | SORT @timestamp DESC ; -_index:keyword | @timestamp:datetime | foo:keyword | message:keyword | unmapped_message:keyword +_index:keyword | @timestamp:datetime | foo:keyword | message:keyword | unmapped_message:keyword partial_mapping_sample_data | 2024-10-23T13:55:01.543Z | null | Connected to 10.1.0.1! | Disconnected from 10.1.0.1 -partial_mapping_sample_data | 2024-10-23T13:53:55.832Z | null | Connection error? | Disconnection error -partial_mapping_sample_data | 2024-10-23T13:52:55.015Z | null | Connection error? | Disconnection error -partial_mapping_sample_data | 2024-10-23T13:51:54.732Z | null | Connection error? | Disconnection error -partial_mapping_sample_data | 2024-10-23T13:33:34.937Z | null | 42 | 43 +partial_mapping_sample_data | 2024-10-23T13:53:55.832Z | null | Connection error? | Disconnection error +partial_mapping_sample_data | 2024-10-23T13:52:55.015Z | null | Connection error? | Disconnection error +partial_mapping_sample_data | 2024-10-23T13:51:54.732Z | null | Connection error? | Disconnection error +partial_mapping_sample_data | 2024-10-23T13:33:34.937Z | null | 42 | 43 partial_mapping_sample_data | 2024-10-23T12:27:28.948Z | null | Connected to 10.1.0.2! | Disconnected from 10.1.0.2 partial_mapping_sample_data | 2024-10-23T12:15:03.360Z | null | Connected to 10.1.0.3! | Disconnected from 10.1.0.3 -sample_data | 2023-10-23T13:55:01.543Z | null | Connected to 10.1.0.1 | null -sample_data | 2023-10-23T13:53:55.832Z | null | Connection error | null -sample_data | 2023-10-23T13:52:55.015Z | null | Connection error | null -sample_data | 2023-10-23T13:51:54.732Z | null | Connection error | null -sample_data | 2023-10-23T13:33:34.937Z | null | Disconnected | null -sample_data | 2023-10-23T12:27:28.948Z | null | Connected to 10.1.0.2 | null +sample_data | 2023-10-23T13:55:01.543Z | null | Connected to 10.1.0.1 | null +sample_data | 2023-10-23T13:53:55.832Z | null | Connection error | null +sample_data | 2023-10-23T13:52:55.015Z | null | Connection error | null +sample_data | 2023-10-23T13:51:54.732Z | null | Connection error | null +sample_data | 2023-10-23T13:33:34.937Z | null | Disconnected | null +sample_data | 2023-10-23T12:27:28.948Z | null | Connected to 10.1.0.2 | null sample_data | 2023-10-23T12:15:03.360Z | null | Connected to 10.1.0.3 | null ; @@ -413,20 +413,20 @@ FROM partial_mapping_sample_data, sample_data METADATA _index | SORT @timestamp DESC ; -_index:keyword | @timestamp:datetime | foo:keyword | message:keyword | unmapped_message:keyword +_index:keyword | @timestamp:datetime | foo:keyword | message:keyword | unmapped_message:keyword partial_mapping_sample_data | 2024-10-23T13:55:01.543Z | null | Connected to 10.1.0.1! | Disconnected from 10.1.0.1 -partial_mapping_sample_data | 2024-10-23T13:53:55.832Z | null | Connection error? | Disconnection error -partial_mapping_sample_data | 2024-10-23T13:52:55.015Z | null | Connection error? | Disconnection error -partial_mapping_sample_data | 2024-10-23T13:51:54.732Z | null | Connection error? | Disconnection error -partial_mapping_sample_data | 2024-10-23T13:33:34.937Z | null | 42 | 43 +partial_mapping_sample_data | 2024-10-23T13:53:55.832Z | null | Connection error? | Disconnection error +partial_mapping_sample_data | 2024-10-23T13:52:55.015Z | null | Connection error? | Disconnection error +partial_mapping_sample_data | 2024-10-23T13:51:54.732Z | null | Connection error? | Disconnection error +partial_mapping_sample_data | 2024-10-23T13:33:34.937Z | null | 42 | 43 partial_mapping_sample_data | 2024-10-23T12:27:28.948Z | null | Connected to 10.1.0.2! | Disconnected from 10.1.0.2 partial_mapping_sample_data | 2024-10-23T12:15:03.360Z | null | Connected to 10.1.0.3! | Disconnected from 10.1.0.3 -sample_data | 2023-10-23T13:55:01.543Z | null | Connected to 10.1.0.1 | null -sample_data | 2023-10-23T13:53:55.832Z | null | Connection error | null -sample_data | 2023-10-23T13:52:55.015Z | null | Connection error | null -sample_data | 2023-10-23T13:51:54.732Z | null | Connection error | null -sample_data | 2023-10-23T13:33:34.937Z | null | Disconnected | null -sample_data | 2023-10-23T12:27:28.948Z | null | Connected to 10.1.0.2 | null +sample_data | 2023-10-23T13:55:01.543Z | null | Connected to 10.1.0.1 | null +sample_data | 2023-10-23T13:53:55.832Z | null | Connection error | null +sample_data | 2023-10-23T13:52:55.015Z | null | Connection error | null +sample_data | 2023-10-23T13:51:54.732Z | null | Connection error | null +sample_data | 2023-10-23T13:33:34.937Z | null | Disconnected | null +sample_data | 2023-10-23T12:27:28.948Z | null | Connected to 10.1.0.2 | null sample_data | 2023-10-23T12:15:03.360Z | null | Connected to 10.1.0.3 | null ; @@ -748,3 +748,21 @@ integer:integer | alias_integer:integer | does_not_exist:keyword 4 | 4 | null 5 | 5 | null ; + +filterOnPartiallyUnmappedField +required_capability: index_metadata_field +required_capability: unmapped_fields +required_capability: optional_fields + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| KEEP _index, message +| WHERE message == "Connection error?" +| SORT _index +; + +_index:keyword | message:keyword +no_mapping_sample_data | Connection error? +no_mapping_sample_data | Connection error? +no_mapping_sample_data | Connection error? +; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/LucenePushdownPredicates.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/LucenePushdownPredicates.java index aa9ea3b0e004b..3bb67a9a5c8f3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/LucenePushdownPredicates.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/LucenePushdownPredicates.java @@ -15,6 +15,7 @@ import org.elasticsearch.xpack.esql.core.expression.MetadataAttribute; import org.elasticsearch.xpack.esql.core.expression.TypedAttribute; import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.core.type.PotentiallyUnmappedKeywordEsField; import org.elasticsearch.xpack.esql.core.util.Check; import org.elasticsearch.xpack.esql.plugin.EsqlFlags; import org.elasticsearch.xpack.esql.stats.SearchStats; @@ -82,7 +83,10 @@ public interface LucenePushdownPredicates { * support it, and relying on the compute engine for the nodes that do not. */ default boolean isPushableFieldAttribute(Expression exp) { - if (exp instanceof FieldAttribute fa && fa.getExactInfo().hasExact() && isIndexedAndHasDocValues(fa)) { + if (exp instanceof FieldAttribute fa + && fa.field() instanceof PotentiallyUnmappedKeywordEsField == false + && fa.getExactInfo().hasExact() + && isIndexedAndHasDocValues(fa)) { return fa.dataType() != DataType.TEXT || hasExactSubfield(fa); } return false; From a5536c053e9b0adcf9610e562a4922e441894c1a Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 9 Feb 2026 16:14:43 +0200 Subject: [PATCH 027/137] Add test for sort pushdown on partially unmapped fields (#141925) The isPushableFieldAttribute fix (rejecting PotentiallyUnmappedKeywordEsField) already covers sort pushdown since PushTopNToSource uses the same method. This test verifies correct sort order when a field is mapped in one index but unmapped in another under unmapped_fields="load". Co-authored-by: Cursor --- .../src/main/resources/unmapped-load.csv-spec | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index 0a3990c33c1fa..d373dd71d0542 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -766,3 +766,23 @@ no_mapping_sample_data | Connection error? no_mapping_sample_data | Connection error? no_mapping_sample_data | Connection error? ; + +sortOnPartiallyUnmappedField +required_capability: index_metadata_field +required_capability: unmapped_fields +required_capability: optional_fields + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| KEEP _index, message +| SORT message, _index +| LIMIT 5 +; + +_index:keyword | message:keyword +no_mapping_sample_data | 42 +sample_data | Connected to 10.1.0.1 +no_mapping_sample_data | Connected to 10.1.0.1! +sample_data | Connected to 10.1.0.2 +no_mapping_sample_data | Connected to 10.1.0.2! +; From 6980de7530bee5d20b9d60b642989896a3307f0e Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 9 Feb 2026 16:25:39 +0200 Subject: [PATCH 028/137] Fix sort pushdown test to actually exercise the bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove _index from the SORT clause — it prevented the entire sort from being pushed to Lucene (canPushDownOrders requires all fields pushable), masking the bug. With only SORT message, the sort is pushed down and produces wrong order on the unmapped shard without the fix. Co-authored-by: Cursor --- .../qa/testFixtures/src/main/resources/unmapped-load.csv-spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index d373dd71d0542..86974629db487 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -775,7 +775,7 @@ required_capability: optional_fields SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data METADATA _index | KEEP _index, message -| SORT message, _index +| SORT message | LIMIT 5 ; From 8fc5cf9bf77a7ecefad4f2c509f759e44b419e1b Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 9 Feb 2026 22:03:39 +0200 Subject: [PATCH 029/137] TEMP refactor and add failing tests --- .../esql/analysis/AnalyzerTestUtils.java | 35 +++++ .../xpack/esql/analysis/AnalyzerTests.java | 145 ++++++------------ .../esql/analysis/AnalyzerUnmappedTests.java | 71 +++++++++ 3 files changed, 151 insertions(+), 100 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java index e3383412e9027..4b36f01284ee6 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java @@ -8,6 +8,11 @@ package org.elasticsearch.xpack.esql.analysis; import org.elasticsearch.TransportVersion; +import org.elasticsearch.action.fieldcaps.FieldCapabilitiesIndexResponse; +import org.elasticsearch.action.fieldcaps.FieldCapabilitiesResponse; +import org.elasticsearch.action.fieldcaps.IndexFieldCapabilities; +import org.elasticsearch.action.fieldcaps.IndexFieldCapabilitiesBuilder; +import org.elasticsearch.common.hash.MessageDigests; import org.elasticsearch.core.Nullable; import org.elasticsearch.index.IndexMode; import org.elasticsearch.inference.TaskType; @@ -31,7 +36,9 @@ import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.esql.plan.logical.UnresolvedRelation; import org.elasticsearch.xpack.esql.session.Configuration; +import org.elasticsearch.xpack.esql.session.IndexResolver; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -488,4 +495,32 @@ public static IndexResolution indexWithDateDateNanosUnionType() { ); return IndexResolution.valid(index); } + + public static FieldCapabilitiesIndexResponse fieldCapabilitiesIndexResponse( + String indexName, + Map fields + ) { + String indexMappingHash = new String( + MessageDigests.sha256().digest(fields.toString().getBytes(StandardCharsets.UTF_8)), + StandardCharsets.UTF_8 + ); + return new FieldCapabilitiesIndexResponse(indexName, indexMappingHash, fields, false, IndexMode.STANDARD); + } + + public static Map fieldResponseMap(String fieldName, String type) { + return Map.of(fieldName, new IndexFieldCapabilitiesBuilder(fieldName, type).build()); + } + + public static IndexResolver.FieldsInfo fieldsInfoOnCurrentVersion(FieldCapabilitiesResponse caps) { + return new IndexResolver.FieldsInfo(caps, TransportVersion.current(), false, false, false); + } + + public static IndexResolution mergedResolution(String indexPattern, FieldCapabilitiesResponse caps) { + return IndexResolver.mergedMappings( + indexPattern, + false, + fieldsInfoOnCurrentVersion(caps), + IndexResolver.DO_NOT_GROUP + ); + } } 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 e0c9d419abb6c..d283b0d67edd2 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 @@ -14,7 +14,6 @@ import org.elasticsearch.action.fieldcaps.FieldCapabilitiesResponse; import org.elasticsearch.action.fieldcaps.IndexFieldCapabilities; import org.elasticsearch.action.fieldcaps.IndexFieldCapabilitiesBuilder; -import org.elasticsearch.common.hash.MessageDigests; import org.elasticsearch.common.lucene.BytesRefs; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.IndexMode; @@ -115,7 +114,6 @@ import org.elasticsearch.xpack.esql.session.IndexResolver; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.time.Period; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -149,7 +147,11 @@ import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyzerDefaultMapping; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.defaultEnrichResolution; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.defaultInferenceResolution; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.fieldCapabilitiesIndexResponse; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.fieldResponseMap; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.fieldsInfoOnCurrentVersion; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.indexResolutions; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.mergedResolution; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.indexWithDateDateNanosUnionType; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.loadMapping; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.randomInferenceIdOtherThan; @@ -3171,20 +3173,14 @@ public void testResolveInsist_fieldDoesNotExist_createsUnmappedField() { public void testResolveInsist_multiIndexFieldPartiallyMappedWithSingleKeywordType_createsUnmappedField() { assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); - IndexResolution resolution = IndexResolver.mergedMappings( - "foo,bar", - false, - fieldsInfoOnCurrentVersion( - new FieldCapabilitiesResponse( - List.of( - fieldCapabilitiesIndexResponse("foo", messageResponseMap("keyword")), - fieldCapabilitiesIndexResponse("bar", Map.of()) - ), - List.of() - ) + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "keyword")), + fieldCapabilitiesIndexResponse("bar", Map.of()) ), - IndexResolver.DO_NOT_GROUP + List.of() ); + IndexResolution resolution = mergedResolution("foo,bar", caps); String query = "FROM foo, bar | INSIST_🐔 message"; var plan = analyze(query, analyzer(indexResolutions(resolution), TEST_VERIFIER, configuration(query))); @@ -3198,20 +3194,14 @@ public void testResolveInsist_multiIndexFieldPartiallyMappedWithSingleKeywordTyp public void testResolveInsist_multiIndexFieldExistsWithSingleTypeButIsNotKeywordAndMissingCast_createsAnInvalidMappedField() { assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); - IndexResolution resolution = IndexResolver.mergedMappings( - "foo,bar", - false, - fieldsInfoOnCurrentVersion( - new FieldCapabilitiesResponse( - List.of( - fieldCapabilitiesIndexResponse("foo", messageResponseMap("long")), - fieldCapabilitiesIndexResponse("bar", Map.of()) - ), - List.of() - ) + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "long")), + fieldCapabilitiesIndexResponse("bar", Map.of()) ), - IndexResolver.DO_NOT_GROUP + List.of() ); + IndexResolution resolution = mergedResolution("foo,bar", caps); var plan = analyze("FROM foo, bar | INSIST_🐔 message", analyzer(resolution, TEST_VERIFIER)); var limit = as(plan, Limit.class); var insist = as(limit.child(), Insist.class); @@ -3226,21 +3216,15 @@ public void testResolveInsist_multiIndexFieldExistsWithSingleTypeButIsNotKeyword public void testResolveInsist_multiIndexFieldPartiallyExistsWithMultiTypesNoKeyword_createsAnInvalidMappedField() { assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); - IndexResolution resolution = IndexResolver.mergedMappings( - "foo,bar", - false, - fieldsInfoOnCurrentVersion( - new FieldCapabilitiesResponse( - List.of( - fieldCapabilitiesIndexResponse("foo", messageResponseMap("long")), - fieldCapabilitiesIndexResponse("bar", messageResponseMap("date")), - fieldCapabilitiesIndexResponse("bazz", Map.of()) - ), - List.of() - ) + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "long")), + fieldCapabilitiesIndexResponse("bar", fieldResponseMap("message", "date")), + fieldCapabilitiesIndexResponse("bazz", Map.of()) ), - IndexResolver.DO_NOT_GROUP + List.of() ); + IndexResolution resolution = mergedResolution("foo,bar", caps); var plan = analyze("FROM foo, bar | INSIST_🐔 message", analyzer(resolution, TEST_VERIFIER)); var limit = as(plan, Limit.class); var insist = as(limit.child(), Insist.class); @@ -3254,20 +3238,14 @@ public void testResolveInsist_multiIndexFieldPartiallyExistsWithMultiTypesNoKeyw public void testResolveInsist_multiIndexSameMapping_fieldIsMapped() { assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); - IndexResolution resolution = IndexResolver.mergedMappings( - "foo,bar", - false, - fieldsInfoOnCurrentVersion( - new FieldCapabilitiesResponse( - List.of( - fieldCapabilitiesIndexResponse("foo", messageResponseMap("long")), - fieldCapabilitiesIndexResponse("bar", messageResponseMap("long")) - ), - List.of() - ) + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "long")), + fieldCapabilitiesIndexResponse("bar", fieldResponseMap("message", "long")) ), - IndexResolver.DO_NOT_GROUP + List.of() ); + IndexResolution resolution = mergedResolution("foo,bar", caps); var plan = analyze("FROM foo, bar | INSIST_🐔 message", analyzer(resolution, TEST_VERIFIER)); var limit = as(plan, Limit.class); var insist = as(limit.child(), Insist.class); @@ -3279,22 +3257,16 @@ public void testResolveInsist_multiIndexSameMapping_fieldIsMapped() { public void testResolveInsist_multiIndexFieldPartiallyExistsWithMultiTypesWithKeyword_createsAnInvalidMappedField() { assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); - IndexResolution resolution = IndexResolver.mergedMappings( - "foo,bar", - false, - fieldsInfoOnCurrentVersion( - new FieldCapabilitiesResponse( - List.of( - fieldCapabilitiesIndexResponse("foo", messageResponseMap("long")), - fieldCapabilitiesIndexResponse("bar", messageResponseMap("date")), - fieldCapabilitiesIndexResponse("bazz", messageResponseMap("keyword")), - fieldCapabilitiesIndexResponse("qux", Map.of()) - ), - List.of() - ) + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "long")), + fieldCapabilitiesIndexResponse("bar", fieldResponseMap("message", "date")), + fieldCapabilitiesIndexResponse("bazz", fieldResponseMap("message", "keyword")), + fieldCapabilitiesIndexResponse("qux", Map.of()) ), - IndexResolver.DO_NOT_GROUP + List.of() ); + IndexResolution resolution = mergedResolution("foo,bar", caps); var plan = analyze("FROM foo, bar | INSIST_🐔 message", analyzer(resolution, TEST_VERIFIER)); var limit = as(plan, Limit.class); var insist = as(limit.child(), Insist.class); @@ -3308,21 +3280,15 @@ public void testResolveInsist_multiIndexFieldPartiallyExistsWithMultiTypesWithKe public void testResolveInsist_multiIndexFieldPartiallyExistsWithMultiTypesWithCast_castsAreNotSupported() { assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); - IndexResolution resolution = IndexResolver.mergedMappings( - "foo,bar", - false, - fieldsInfoOnCurrentVersion( - new FieldCapabilitiesResponse( - List.of( - fieldCapabilitiesIndexResponse("foo", messageResponseMap("long")), - fieldCapabilitiesIndexResponse("bar", messageResponseMap("date")), - fieldCapabilitiesIndexResponse("bazz", Map.of()) - ), - List.of() - ) + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "long")), + fieldCapabilitiesIndexResponse("bar", fieldResponseMap("message", "date")), + fieldCapabilitiesIndexResponse("bazz", Map.of()) ), - IndexResolver.DO_NOT_GROUP + List.of() ); + IndexResolution resolution = mergedResolution("foo,bar", caps); VerificationException e = expectThrows( VerificationException.class, () -> analyze("FROM foo, bar | INSIST_🐔 message | EVAL message = message :: keyword", analyzer(resolution, TEST_VERIFIER)) @@ -3772,22 +3738,6 @@ public void testFuseError() { assertThat(e.getMessage(), containsString("Unknown column [_id]")); } - // TODO There's too much boilerplate involved here! We need a better way of creating FieldCapabilitiesResponses from a mapping or index. - private static FieldCapabilitiesIndexResponse fieldCapabilitiesIndexResponse( - String indexName, - Map fields - ) { - String indexMappingHash = new String( - MessageDigests.sha256().digest(fields.toString().getBytes(StandardCharsets.UTF_8)), - StandardCharsets.UTF_8 - ); - return new FieldCapabilitiesIndexResponse(indexName, indexMappingHash, fields, false, IndexMode.STANDARD); - } - - private static Map messageResponseMap(String date) { - return Map.of("message", new IndexFieldCapabilitiesBuilder("message", date).build()); - } - private void verifyUnsupported(String query, String errorMessage) { verifyUnsupported(query, errorMessage, "mapping-multi-field-variation.json"); } @@ -3845,8 +3795,7 @@ private static LogicalPlan analyzeWithEmptyFieldCapsResponse(String query) throw List idxResponses = List.of( new FieldCapabilitiesIndexResponse("idx", "idx", Map.of(), true, IndexMode.STANDARD) ); - IndexResolver.FieldsInfo caps = fieldsInfoOnCurrentVersion(new FieldCapabilitiesResponse(idxResponses, List.of())); - IndexResolution resolution = IndexResolver.mergedMappings("test*", false, caps, IndexResolver.DO_NOT_GROUP); + IndexResolution resolution = mergedResolution("test*", new FieldCapabilitiesResponse(idxResponses, List.of())); var analyzer = analyzer(indexResolutions(resolution), TEST_VERIFIER, configuration(query)); return analyze(query, analyzer); } @@ -6111,8 +6060,4 @@ static Literal string(String value) { static Literal literal(int value) { return new Literal(EMPTY, value, INTEGER); } - - static IndexResolver.FieldsInfo fieldsInfoOnCurrentVersion(FieldCapabilitiesResponse caps) { - return new IndexResolver.FieldsInfo(caps, TransportVersion.current(), false, false, false); - } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index 7c8d614902616..0a5eb00d1c616 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -7,9 +7,12 @@ package org.elasticsearch.xpack.esql.analysis; +import org.elasticsearch.action.fieldcaps.FieldCapabilitiesResponse; +import org.elasticsearch.action.fieldcaps.IndexFieldCapabilities; import org.elasticsearch.index.IndexMode; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.esql.VerificationException; +import org.elasticsearch.xpack.esql.index.IndexResolution; import org.elasticsearch.xpack.esql.action.EsqlCapabilities; import org.elasticsearch.xpack.esql.core.expression.Alias; import org.elasticsearch.xpack.esql.core.expression.Expressions; @@ -52,10 +55,20 @@ import org.elasticsearch.xpack.esql.plan.logical.join.JoinTypes; import org.elasticsearch.xpack.esql.plan.logical.join.LookupJoin; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static org.elasticsearch.xpack.esql.EsqlTestUtils.as; +import static org.elasticsearch.xpack.esql.EsqlTestUtils.configuration; +import static org.elasticsearch.xpack.esql.EsqlTestUtils.TEST_VERIFIER; import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyze; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyzer; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.fieldCapabilitiesIndexResponse; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.fieldResponseMap; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.indexResolutions; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.mergedResolution; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyzeStatement; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTests.withInlinestatsWarning; import static org.hamcrest.Matchers.contains; @@ -3375,6 +3388,12 @@ private void verificationFailure(String statement, String expectedFailure) { assertThat(e.getMessage(), containsString(expectedFailure)); } + private void verificationFailureWithResolution(String statement, String expectedFailure, IndexResolution resolution) { + var a = analyzer(indexResolutions(resolution), TEST_VERIFIER, configuration(statement)); + var e = expectThrows(VerificationException.class, () -> analyze(statement, a)); + assertThat(e.getMessage(), containsString(expectedFailure)); + } + private static String setUnmappedNullify(String query) { assumeTrue("Requires OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW", EsqlCapabilities.Cap.OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW.isEnabled()); return "SET unmapped_fields=\"nullify\"; " + query; @@ -3385,6 +3404,58 @@ private static String setUnmappedLoad(String query) { return "SET unmapped_fields=\"load\"; " + query; } + public void partiallyUnmappedKeywordMultiIndexFailsWithLoad() { + assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); + Map fooFields = new HashMap<>(); + fooFields.putAll(fieldResponseMap("@timestamp", "date")); + fooFields.putAll(fieldResponseMap("message", "keyword")); + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fooFields), + fieldCapabilitiesIndexResponse("bar", Map.of()) + ), + List.of() + ); + IndexResolution resolution = mergedResolution("foo,bar", caps); + String query = "FROM foo, bar METADATA _index | KEEP _index, @timestamp, message | SORT _index, @timestamp DESC"; + verificationFailureWithResolution(setUnmappedLoad(query), "Cannot use field [@timestamp] due to ambiguities", resolution); + } + + public void partiallyUnmappedNonKeywordMultiIndexCastFailsWithLoad() { + assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); + Map fooFields = new HashMap<>(); + fooFields.putAll(fieldResponseMap("@timestamp", "date")); + fooFields.putAll(fieldResponseMap("event_duration", "long")); + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fooFields), + fieldCapabilitiesIndexResponse("bar", Map.of()) + ), + List.of() + ); + IndexResolution resolution = mergedResolution("foo,bar", caps); + String query = "FROM foo, bar METADATA _index | EVAL duration = event_duration::DOUBLE | KEEP _index, @timestamp, duration | SORT _index, @timestamp DESC"; + verificationFailureWithResolution(setUnmappedLoad(query), "incompatible types", resolution); + } + + public void partiallyUnmappedMixedTypesMultiIndexCastFailsWithLoad() { + assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); + Map fooBarFields = new HashMap<>(); + fooBarFields.putAll(fieldResponseMap("@timestamp", "date")); + fooBarFields.putAll(fieldResponseMap("message", "keyword")); + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fooBarFields), + fieldCapabilitiesIndexResponse("bar", fooBarFields), + fieldCapabilitiesIndexResponse("bazz", Map.of()) + ), + List.of() + ); + IndexResolution resolution = mergedResolution("foo,bar,bazz", caps); + String query = "FROM foo, bar, bazz METADATA _index | EVAL msg = message::KEYWORD | KEEP _index, @timestamp, msg | SORT _index, @timestamp DESC"; + verificationFailureWithResolution(setUnmappedLoad(query), "Cannot use field [@timestamp] due to ambiguities", resolution); + } + @Override protected List filteredWarnings() { return withInlinestatsWarning(withDefaultLimitWarning(super.filteredWarnings())); From 0dcb78bd4269011bd80cfe32e9a3ef022afb9cfb Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 9 Feb 2026 22:21:58 +0200 Subject: [PATCH 030/137] Small refactors --- .../esql/analysis/AnalyzerTestUtils.java | 15 +++++---- .../xpack/esql/analysis/AnalyzerTests.java | 4 +-- .../esql/analysis/AnalyzerUnmappedTests.java | 33 ++++++++----------- 3 files changed, 23 insertions(+), 29 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java index 4b36f01284ee6..dc2b046ed934d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java @@ -511,16 +511,19 @@ public static Map fieldResponseMap(String fieldN return Map.of(fieldName, new IndexFieldCapabilitiesBuilder(fieldName, type).build()); } + public static Map fieldResponseMap(Map fieldTypes) { + Map result = new HashMap<>(); + for (Map.Entry entry : fieldTypes.entrySet()) { + result.putAll(fieldResponseMap(entry.getKey(), entry.getValue())); + } + return result; + } + public static IndexResolver.FieldsInfo fieldsInfoOnCurrentVersion(FieldCapabilitiesResponse caps) { return new IndexResolver.FieldsInfo(caps, TransportVersion.current(), false, false, false); } public static IndexResolution mergedResolution(String indexPattern, FieldCapabilitiesResponse caps) { - return IndexResolver.mergedMappings( - indexPattern, - false, - fieldsInfoOnCurrentVersion(caps), - IndexResolver.DO_NOT_GROUP - ); + return IndexResolver.mergedMappings(indexPattern, false, fieldsInfoOnCurrentVersion(caps), IndexResolver.DO_NOT_GROUP); } } 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 d283b0d67edd2..f59970e8fa493 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 @@ -12,7 +12,6 @@ import org.elasticsearch.TransportVersion; import org.elasticsearch.action.fieldcaps.FieldCapabilitiesIndexResponse; import org.elasticsearch.action.fieldcaps.FieldCapabilitiesResponse; -import org.elasticsearch.action.fieldcaps.IndexFieldCapabilities; import org.elasticsearch.action.fieldcaps.IndexFieldCapabilitiesBuilder; import org.elasticsearch.common.lucene.BytesRefs; import org.elasticsearch.common.settings.Settings; @@ -149,11 +148,10 @@ import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.defaultInferenceResolution; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.fieldCapabilitiesIndexResponse; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.fieldResponseMap; -import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.fieldsInfoOnCurrentVersion; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.indexResolutions; -import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.mergedResolution; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.indexWithDateDateNanosUnionType; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.loadMapping; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.mergedResolution; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.randomInferenceIdOtherThan; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.tsdbIndexResolution; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.unresolvedRelation; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index 0a5eb00d1c616..ee881d05ca01e 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -12,7 +12,6 @@ import org.elasticsearch.index.IndexMode; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.esql.VerificationException; -import org.elasticsearch.xpack.esql.index.IndexResolution; import org.elasticsearch.xpack.esql.action.EsqlCapabilities; import org.elasticsearch.xpack.esql.core.expression.Alias; import org.elasticsearch.xpack.esql.core.expression.Expressions; @@ -37,6 +36,7 @@ import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.Add; import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.GreaterThan; import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.LessThan; +import org.elasticsearch.xpack.esql.index.IndexResolution; import org.elasticsearch.xpack.esql.plan.logical.Aggregate; import org.elasticsearch.xpack.esql.plan.logical.Dissect; import org.elasticsearch.xpack.esql.plan.logical.Enrich; @@ -55,21 +55,20 @@ import org.elasticsearch.xpack.esql.plan.logical.join.JoinTypes; import org.elasticsearch.xpack.esql.plan.logical.join.LookupJoin; -import java.util.HashMap; import java.util.List; import java.util.Map; +import static org.elasticsearch.xpack.esql.EsqlTestUtils.TEST_VERIFIER; import static org.elasticsearch.xpack.esql.EsqlTestUtils.as; import static org.elasticsearch.xpack.esql.EsqlTestUtils.configuration; -import static org.elasticsearch.xpack.esql.EsqlTestUtils.TEST_VERIFIER; import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyze; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyzeStatement; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyzer; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.fieldCapabilitiesIndexResponse; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.fieldResponseMap; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.indexResolutions; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.mergedResolution; -import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyzeStatement; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTests.withInlinestatsWarning; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; @@ -3404,14 +3403,11 @@ private static String setUnmappedLoad(String query) { return "SET unmapped_fields=\"load\"; " + query; } - public void partiallyUnmappedKeywordMultiIndexFailsWithLoad() { + public void testPartiallyUnmappedKeywordFailsWithLoad() { assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); - Map fooFields = new HashMap<>(); - fooFields.putAll(fieldResponseMap("@timestamp", "date")); - fooFields.putAll(fieldResponseMap("message", "keyword")); FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( List.of( - fieldCapabilitiesIndexResponse("foo", fooFields), + fieldCapabilitiesIndexResponse("foo", fieldResponseMap(Map.of("@timestamp", "date", "message", "keyword"))), fieldCapabilitiesIndexResponse("bar", Map.of()) ), List.of() @@ -3421,28 +3417,24 @@ public void partiallyUnmappedKeywordMultiIndexFailsWithLoad() { verificationFailureWithResolution(setUnmappedLoad(query), "Cannot use field [@timestamp] due to ambiguities", resolution); } - public void partiallyUnmappedNonKeywordMultiIndexCastFailsWithLoad() { + public void testPartiallyUnmappedNonKeywordFailsWithLoad() { assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); - Map fooFields = new HashMap<>(); - fooFields.putAll(fieldResponseMap("@timestamp", "date")); - fooFields.putAll(fieldResponseMap("event_duration", "long")); FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( List.of( - fieldCapabilitiesIndexResponse("foo", fooFields), + fieldCapabilitiesIndexResponse("foo", fieldResponseMap(Map.of("@timestamp", "date", "message", "keyword"))), fieldCapabilitiesIndexResponse("bar", Map.of()) ), List.of() ); IndexResolution resolution = mergedResolution("foo,bar", caps); - String query = "FROM foo, bar METADATA _index | EVAL duration = event_duration::DOUBLE | KEEP _index, @timestamp, duration | SORT _index, @timestamp DESC"; + String query = + "FROM foo, bar METADATA _index | EVAL duration = event_duration::DOUBLE | KEEP _index, @timestamp, duration | SORT _index, @timestamp DESC"; verificationFailureWithResolution(setUnmappedLoad(query), "incompatible types", resolution); } - public void partiallyUnmappedMixedTypesMultiIndexCastFailsWithLoad() { + public void testPartiallyUnmappedMixedTypesWithCastFailsWithLoad() { assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); - Map fooBarFields = new HashMap<>(); - fooBarFields.putAll(fieldResponseMap("@timestamp", "date")); - fooBarFields.putAll(fieldResponseMap("message", "keyword")); + Map fooBarFields = fieldResponseMap(Map.of("@timestamp", "date", "message", "keyword")); FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( List.of( fieldCapabilitiesIndexResponse("foo", fooBarFields), @@ -3452,7 +3444,8 @@ public void partiallyUnmappedMixedTypesMultiIndexCastFailsWithLoad() { List.of() ); IndexResolution resolution = mergedResolution("foo,bar,bazz", caps); - String query = "FROM foo, bar, bazz METADATA _index | EVAL msg = message::KEYWORD | KEEP _index, @timestamp, msg | SORT _index, @timestamp DESC"; + String query = + "FROM foo, bar, bazz METADATA _index | EVAL msg = message::KEYWORD | KEEP _index, @timestamp, msg | SORT _index, @timestamp DESC"; verificationFailureWithResolution(setUnmappedLoad(query), "Cannot use field [@timestamp] due to ambiguities", resolution); } From c0263bfd885873d48bf0d95ffedb5c1cb32cd20f Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 9 Feb 2026 22:34:04 +0200 Subject: [PATCH 031/137] Temp 2 --- .../xpack/esql/analysis/AnalyzerTestUtils.java | 6 ++++++ .../xpack/esql/analysis/AnalyzerUnmappedTests.java | 5 ++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java index dc2b046ed934d..0899043820109 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java @@ -187,6 +187,12 @@ public static LogicalPlan analyzeStatement(String query) { return analyzer.analyze(statement.plan()); } + public static LogicalPlan analyzeStatement(String query, Map indexResolutions) { + var statement = EsqlParser.INSTANCE.createStatement(query); + var analyzer = analyzer(indexResolutions, TEST_VERIFIER, configuration(query), statement); + return analyzer.analyze(statement.plan()); + } + public static LogicalPlan analyze(String query, String mapping) { return analyze(query, indexFromQuery(query), mapping); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index ee881d05ca01e..54fd1e73da459 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -3387,9 +3387,8 @@ private void verificationFailure(String statement, String expectedFailure) { assertThat(e.getMessage(), containsString(expectedFailure)); } - private void verificationFailureWithResolution(String statement, String expectedFailure, IndexResolution resolution) { - var a = analyzer(indexResolutions(resolution), TEST_VERIFIER, configuration(statement)); - var e = expectThrows(VerificationException.class, () -> analyze(statement, a)); + private void verificationFailureWithResolution(String statementWithSet, String expectedFailure, IndexResolution resolution) { + var e = expectThrows(VerificationException.class, () -> analyzeStatement(statementWithSet, indexResolutions(resolution))); assertThat(e.getMessage(), containsString(expectedFailure)); } From ae46470018f52d2579ed4e0876f310d8256744e8 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 9 Feb 2026 22:34:04 +0200 Subject: [PATCH 032/137] Temp 2 --- .../fulltext/SingleFieldFullTextFunction.java | 3 +- .../esql/analysis/AnalyzerTestUtils.java | 4 +- .../esql/analysis/AnalyzerUnmappedTests.java | 42 +++++++++---------- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/SingleFieldFullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/SingleFieldFullTextFunction.java index aa45a44eeff76..3f8f1818af594 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/SingleFieldFullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/SingleFieldFullTextFunction.java @@ -240,6 +240,7 @@ protected String expectedQueryTypesString() { } static String expectedTypesAsString(Set dataTypes) { - return String.join(", ", dataTypes.stream().map(dt -> dt.name().toLowerCase(Locale.ROOT)).toList()); + // FIXME(gal, NOCOMMIT) Extract this to a separate PR. + return String.join(", ", dataTypes.stream().map(dt -> dt.name().toLowerCase(Locale.ROOT)).sorted().toList()); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java index 0899043820109..23e6d543c6fb3 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java @@ -182,9 +182,7 @@ public static LogicalPlan analyzeStatement(String query) { var statement = EsqlParser.INSTANCE.createStatement(query); var relations = statement.plan().collectFirstChildren(UnresolvedRelation.class::isInstance); var indexName = relations.isEmpty() ? null : ((UnresolvedRelation) relations.getFirst()).indexPattern().indexPattern(); - var indexResolutions = indexResolutions(indexName); - var analyzer = analyzer(indexResolutions, TEST_VERIFIER, configuration(query), statement); - return analyzer.analyze(statement.plan()); + return analyzeStatement(query, indexResolutions(indexName)); } public static LogicalPlan analyzeStatement(String query, Map indexResolutions) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index 54fd1e73da459..ceea1178b11c3 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -58,15 +58,10 @@ import java.util.List; import java.util.Map; -import static org.elasticsearch.xpack.esql.EsqlTestUtils.TEST_VERIFIER; import static org.elasticsearch.xpack.esql.EsqlTestUtils.as; -import static org.elasticsearch.xpack.esql.EsqlTestUtils.configuration; import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning; -import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyze; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyzeStatement; -import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyzer; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.fieldCapabilitiesIndexResponse; -import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.fieldResponseMap; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.indexResolutions; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.mergedResolution; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTests.withInlinestatsWarning; @@ -80,6 +75,9 @@ // @TestLogging(value = "org.elasticsearch.xpack.esql:TRACE", reason = "debug") public class AnalyzerUnmappedTests extends ESTestCase { + private static final Map TIMESTAMP_MESSAGE_CAPS = AnalyzerTestUtils.fieldResponseMap( + Map.of("@timestamp", "date", "message", "keyword") + ); /* * Limit[1000[INTEGER],false,false] @@ -3405,46 +3403,48 @@ private static String setUnmappedLoad(String query) { public void testPartiallyUnmappedKeywordFailsWithLoad() { assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( - List.of( - fieldCapabilitiesIndexResponse("foo", fieldResponseMap(Map.of("@timestamp", "date", "message", "keyword"))), - fieldCapabilitiesIndexResponse("bar", Map.of()) - ), + List.of(fieldCapabilitiesIndexResponse("foo", TIMESTAMP_MESSAGE_CAPS), fieldCapabilitiesIndexResponse("bar", Map.of())), List.of() ); IndexResolution resolution = mergedResolution("foo,bar", caps); - String query = "FROM foo, bar METADATA _index | KEEP _index, @timestamp, message | SORT _index, @timestamp DESC"; + String query = """ + FROM foo, bar METADATA _index + | KEEP _index, @timestamp, message + | SORT _index, @timestamp DESC"""; verificationFailureWithResolution(setUnmappedLoad(query), "Cannot use field [@timestamp] due to ambiguities", resolution); } public void testPartiallyUnmappedNonKeywordFailsWithLoad() { assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( - List.of( - fieldCapabilitiesIndexResponse("foo", fieldResponseMap(Map.of("@timestamp", "date", "message", "keyword"))), - fieldCapabilitiesIndexResponse("bar", Map.of()) - ), + List.of(fieldCapabilitiesIndexResponse("foo", TIMESTAMP_MESSAGE_CAPS), fieldCapabilitiesIndexResponse("bar", Map.of())), List.of() ); IndexResolution resolution = mergedResolution("foo,bar", caps); - String query = - "FROM foo, bar METADATA _index | EVAL duration = event_duration::DOUBLE | KEEP _index, @timestamp, duration | SORT _index, @timestamp DESC"; + String query = """ + FROM foo, bar METADATA _index + | EVAL duration = event_duration::DOUBLE + | KEEP _index, @timestamp, duration + | SORT _index, @timestamp DESC"""; verificationFailureWithResolution(setUnmappedLoad(query), "incompatible types", resolution); } public void testPartiallyUnmappedMixedTypesWithCastFailsWithLoad() { assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); - Map fooBarFields = fieldResponseMap(Map.of("@timestamp", "date", "message", "keyword")); FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( List.of( - fieldCapabilitiesIndexResponse("foo", fooBarFields), - fieldCapabilitiesIndexResponse("bar", fooBarFields), + fieldCapabilitiesIndexResponse("foo", TIMESTAMP_MESSAGE_CAPS), + fieldCapabilitiesIndexResponse("bar", TIMESTAMP_MESSAGE_CAPS), fieldCapabilitiesIndexResponse("bazz", Map.of()) ), List.of() ); IndexResolution resolution = mergedResolution("foo,bar,bazz", caps); - String query = - "FROM foo, bar, bazz METADATA _index | EVAL msg = message::KEYWORD | KEEP _index, @timestamp, msg | SORT _index, @timestamp DESC"; + String query = """ + FROM foo, bar, bazz METADATA _index + | EVAL msg = message::KEYWORD + | KEEP _index, @timestamp, msg + | SORT _index, @timestamp DESC"""; verificationFailureWithResolution(setUnmappedLoad(query), "Cannot use field [@timestamp] due to ambiguities", resolution); } From 5b2e7ecc1a4b82509856347827f2db695bb46e15 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 10 Feb 2026 18:44:27 +0200 Subject: [PATCH 033/137] Temp hacks with hard coded stuff but working test --- .../src/main/resources/unmapped-load.csv-spec | 26 +++++++++ .../xpack/esql/analysis/Analyzer.java | 19 ++++--- .../esql/core/type/MultiTypeEsField.java | 4 ++ .../local/ReplaceFieldWithConstantOrNull.java | 2 + .../planner/EsPhysicalOperationProviders.java | 55 ++++++++++++++++++- 5 files changed, 95 insertions(+), 11 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index 86974629db487..c766aef112dae 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -786,3 +786,29 @@ no_mapping_sample_data | Connected to 10.1.0.1! sample_data | Connected to 10.1.0.2 no_mapping_sample_data | Connected to 10.1.0.2! ; + +# Type resolution bug: event_duration is long in sample_data, unmapped (loaded) in no_mapping_sample_data; cast to DOUBLE fails to resolve +unmappedLoadEventDurationCastToDouble +required_capability: unmapped_fields +required_capability: optional_fields + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL event_duration = event_duration :: DOUBLE +| KEEP _index, event_duration +| SORT event_duration, _index DESC +| LIMIT 10 +; + +_index:keyword | event_duration:double +no_mapping_sample_data | 725447.0 +sample_data | 725448.0 +no_mapping_sample_data | 1232381.0 +sample_data | 1232382.0 +no_mapping_sample_data | 1756466.0 +sample_data | 1756467.0 +no_mapping_sample_data | 2764888.0 +sample_data | 2764889.0 +no_mapping_sample_data | 3450232.0 +sample_data | 3450233.0 +; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index f4bc28c6910f5..1a5c0edccd7a8 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -14,7 +14,6 @@ import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.Page; -import org.elasticsearch.core.Strings; import org.elasticsearch.index.IndexMode; import org.elasticsearch.logging.Logger; import org.elasticsearch.xpack.core.enrich.EnrichPolicy; @@ -1153,13 +1152,8 @@ private static FieldAttribute invalidInsistAttribute(FieldAttribute fa) { var name = fa.name(); EsField field = fa.field() instanceof InvalidMappedField imf ? new InvalidMappedField(name, InvalidMappedField.makeErrorsMessageIncludingInsistKeyword(imf.getTypesToIndices())) - : new InvalidMappedField( - name, - Strings.format( - "mapped as [2] incompatible types: [keyword] enforced by INSIST command, and [%s] in index mappings", - fa.dataType().typeName() - ) - ); + // FIXME(gal, NOCOMMIT) hard-coded for debugging + : new InvalidMappedField(name, Map.of("long", Set.of("sample_data"), "keyword", Set.of("no_mapping_sample_data"))); return new FieldAttribute(fa.source(), null, fa.qualifier(), name, field); } @@ -2333,7 +2327,14 @@ private static MultiTypeEsField resolvedMultiTypeEsField( typesToConversionExpressions.put(typeName, typeResolutions.get(key)); } }); - return MultiTypeEsField.resolveFrom(imf, typesToConversionExpressions); + // FIXME(gal, NOCOMMIT) more temp hacks + var result = MultiTypeEsField.resolveFrom(imf, typesToConversionExpressions); + result.potentiallyUnmappedExpression = typeResolutions.values() + .stream() + .filter(e -> ((ToDouble) e).field().dataType() == KEYWORD) + .findFirst() + .get(); + return result; } private static boolean canConvertOriginalTypes(MultiTypeEsField multiTypeEsField, Set supportedTypes) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java index b44c608cb92ae..bafd1693d2761 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java @@ -9,6 +9,7 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.core.Nullable; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput; import org.elasticsearch.xpack.esql.io.stream.PlanStreamOutput; @@ -31,6 +32,9 @@ public class MultiTypeEsField extends EsField { private final Map indexToConversionExpressions; + // FIXME(gal, NOCOMMIT) temp + @Nullable + public Expression potentiallyUnmappedExpression = null; public MultiTypeEsField( String name, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java index bbd216342ca5f..6d6a57ad15c12 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java @@ -14,6 +14,7 @@ import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; import org.elasticsearch.xpack.esql.core.expression.Literal; +import org.elasticsearch.xpack.esql.core.type.MultiTypeEsField; import org.elasticsearch.xpack.esql.core.type.PotentiallyUnmappedKeywordEsField; import org.elasticsearch.xpack.esql.optimizer.LocalLogicalOptimizerContext; import org.elasticsearch.xpack.esql.optimizer.rules.RuleUtils; @@ -71,6 +72,7 @@ else if (esRelation.indexMode() == IndexMode.STANDARD) { // Do not use the attribute name, this can deviate from the field name for union types; use fieldName() instead. // Also retain fields from lookup indices because we do not have stats for these. Predicate shouldBeRetained = f -> f.field() instanceof PotentiallyUnmappedKeywordEsField + || f.field() instanceof MultiTypeEsField // FIXME(gal, NOCOMMIT) More temp hacks // The source (or doc) field is added to the relation output as a hack to enable late materialization in the reduce driver. || EsQueryExec.isDocAttribute(f) || localLogicalOptimizerContext.searchStats().exists(f.fieldName()) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java index 9ae955612d7ec..8cc31d06bbf73 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java @@ -201,6 +201,7 @@ private ValuesSourceReaderOperator.LoaderAndConverter blockLoaderAndConverter( MappedFieldType.FieldExtractPreference fieldExtractPreference ) { DefaultShardContext shardContext = (DefaultShardContext) shardContexts.get(shardId); + String indexName = shardContext.ctx.getFullyQualifiedIndex().getName(); if (attr instanceof FieldAttribute fa && fa.field() instanceof PotentiallyUnmappedKeywordEsField kf) { shardContext = new DefaultShardContextForUnmappedField(shardContext, kf); } @@ -212,13 +213,20 @@ private ValuesSourceReaderOperator.LoaderAndConverter blockLoaderAndConverter( } boolean isUnsupported = attr.dataType() == DataType.UNSUPPORTED; String fieldName = getFieldName(attr); - BlockLoader blockLoader = shardContext.blockLoader(fieldName, isUnsupported, fieldExtractPreference, functionConfig); MultiTypeEsField unionTypes = findUnionTypes(attr); + // FIXME(gal, NOCOMMIT) More temp hacks + if (unionTypes != null && indexName.equals("no_mapping_sample_data")) { + shardContext = new DefaultShardContextForUnmappedField2( + shardContext, + new PotentiallyUnmappedKeywordEsField(fieldName), + unionTypes.potentiallyUnmappedExpression + ); + } + BlockLoader blockLoader = shardContext.blockLoader(fieldName, isUnsupported, fieldExtractPreference, functionConfig); if (unionTypes == null) { return ValuesSourceReaderOperator.load(blockLoader); } // Use the fully qualified name `cluster:index-name` because multiple types are resolved on coordinator with the cluster prefix - String indexName = shardContext.ctx.getFullyQualifiedIndex().getName(); Expression conversion = unionTypes.getConversionExpressionForIndex(indexName); if (conversion == null) { return ValuesSourceReaderOperator.LOAD_CONSTANT_NULLS; @@ -271,6 +279,49 @@ static MappedFieldType createUnmappedFieldType(String name, DefaultShardContext } } + // FIXME(gal, NOCOMMIT) document, rename, whatever + private static class DefaultShardContextForUnmappedField2 extends DefaultShardContext { + private static final FieldType UNMAPPED_FIELD_TYPE = new FieldType(KeywordFieldMapper.Defaults.FIELD_TYPE); + static { + UNMAPPED_FIELD_TYPE.setDocValuesType(DocValuesType.NONE); + UNMAPPED_FIELD_TYPE.setIndexOptions(IndexOptions.NONE); + UNMAPPED_FIELD_TYPE.setStored(false); + UNMAPPED_FIELD_TYPE.freeze(); + } + private final KeywordEsField unmappedEsField; + private final Expression converted; + + DefaultShardContextForUnmappedField2( + DefaultShardContext ctx, + PotentiallyUnmappedKeywordEsField unmappedEsField, + Expression converted + ) { + super(ctx.index, ctx.releasable, ctx.ctx, ctx.aliasFilter); + this.unmappedEsField = unmappedEsField; + this.converted = converted; + } + + @Override + public @Nullable MappedFieldType fieldType(String name) { + var superResult = super.fieldType(name); + return superResult == null && name.equals(unmappedEsField.getName()) ? createUnmappedFieldType(name, this) : superResult; + } + + static MappedFieldType createUnmappedFieldType(String name, DefaultShardContext context) { + var builder = new KeywordFieldMapper.Builder(name, context.ctx.getIndexSettings()); + builder.docValues(false); + builder.indexed(false); + return new KeywordFieldMapper.KeywordFieldType( + name, + IndexType.terms(false, false), + new TextSearchInfo(UNMAPPED_FIELD_TYPE, builder.similarity(), Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER), + Lucene.KEYWORD_ANALYZER, + builder, + context.ctx.isSourceSynthetic() + ); + } + } + private static @Nullable MultiTypeEsField findUnionTypes(Attribute attr) { if (attr instanceof FieldAttribute fa && fa.field() instanceof MultiTypeEsField multiTypeEsField) { return multiTypeEsField; From 8ba01d6331933e734c8b79a7851b262acb2cfee6 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 10 Feb 2026 21:29:56 +0200 Subject: [PATCH 034/137] Add golden tests --- .../analysis/AnalyzerUnmappedGoldenTests.java | 17 ++++++++++++----- .../load/analysis.expected | 8 ++++---- .../load/local_physical_optimization.expected | 6 ++++++ .../load/logical_optimization.expected | 3 +++ .../load/physical_optimization.expected | 7 +++++++ .../load/query.esql | 3 ++- 6 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/local_physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/logical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/physical_optimization.expected diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java index 7db188b55c045..7402509e765a8 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -432,8 +432,9 @@ public void testMappedToNonKeywordInOneIndexOnly() throws Exception { public void testMappedToNonKeywordInOneIndexOnlyCast() throws Exception { runTestsLoadOnly(""" FROM sample_data, no_mapping_sample_data - | EVAL x = event_duration :: DOUBLE - """); + | EVAL event_duration = event_duration :: DOUBLE + | KEEP event_duration + """, EnumSet.of(Stage.ANALYSIS, Stage.LOGICAL_OPTIMIZATION, Stage.PHYSICAL_OPTIMIZATION, Stage.LOCAL_PHYSICAL_OPTIMIZATION)); } public void testDifferentTypesAndUnmapped() throws Exception { @@ -484,9 +485,15 @@ private Optional tryRunTestsNullifyOnly(String query) { } private void runTestsLoadOnly(String query) { - var loadException = tryRunTestsLoadOnly(query); - if (loadException.isPresent()) { - throw new RuntimeException("Load mode failed", loadException.get()); + runTestsLoadOnly(query, STAGES); + } + + private void runTestsLoadOnly(String query, EnumSet stages) { + Optional result = EsqlCapabilities.Cap.OPTIONAL_FIELDS.isEnabled() + ? builder(setUnmappedLoad(query)).nestedPath("load").stages(stages).tryRun() + : Optional.empty(); + if (result.isPresent()) { + throw new RuntimeException("Load mode failed", result.get()); } } diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/analysis.expected index 18306fbb2a3b6..e40fa24e6653b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/analysis.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/analysis.expected @@ -1,4 +1,4 @@ -Project[[@timestamp{f(DateEsField)}#0, client_ip{f(EsField)}#1, !event_duration, message{f(KeywordEsField)}#2, x{r}#3]] -\_Limit[1000[INTEGER],false,false] - \_Eval[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#4 AS x#3]] - \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#0, client_ip{f}#1, !event_duration, message{f}#2, $$event_duration$converted_to$double{f$}#4] \ No newline at end of file +Limit[1000[INTEGER],false,false] +\_Project[[event_duration{r}#0]] + \_Eval[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#1 AS event_duration#0]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#5, $$event_duration$converted_to$double{f$}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/local_physical_optimization.expected new file mode 100644 index 0000000000000..51d725ac13932 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/local_physical_optimization.expected @@ -0,0 +1,6 @@ +ProjectExec[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#0 AS event_duration#1]] +\_LimitExec[1000[INTEGER],null] + \_ExchangeExec[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#0],false] + \_ProjectExec[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#0]] + \_FieldExtractExec[$$event_duration$converted_to$double{f$}#0]<[],[]> + \_EsQueryExec[sample_data,no_mapping_sample_data], indexMode[standard], [_doc{f}#2], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/logical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/logical_optimization.expected new file mode 100644 index 0000000000000..162b4ec77ad2a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/logical_optimization.expected @@ -0,0 +1,3 @@ +Project[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#0 AS event_duration#1]] +\_Limit[1000[INTEGER],false,false] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#5, $$event_duration$converted_to$double{f$}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/physical_optimization.expected new file mode 100644 index 0000000000000..49d35b4a9b75b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/physical_optimization.expected @@ -0,0 +1,7 @@ +ProjectExec[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#0 AS event_duration#1]] +\_LimitExec[1000[INTEGER],null] + \_ExchangeExec[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#0],false] + \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> +Project[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#0]] +\_Limit[1000[INTEGER],false,false] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#5, $$event_duration$converted_to$double{f$}#0]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql index 75ac5ca4e241d..4d67c32286e58 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql @@ -1,2 +1,3 @@ SET unmapped_fields="load"; FROM sample_data, no_mapping_sample_data -| EVAL x = event_duration :: DOUBLE +| EVAL event_duration = event_duration :: DOUBLE +| KEEP event_duration From 5194ce58b16fb87134394300a50cb29082042b3b Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 10 Feb 2026 22:58:33 +0200 Subject: [PATCH 035/137] Some fewer hacks --- .../xpack/esql/analysis/Analyzer.java | 31 ++++++++++++++----- .../esql/core/type/InvalidMappedField.java | 29 +++++++++++++++-- .../planner/EsPhysicalOperationProviders.java | 5 ++- .../xpack/esql/session/IndexResolver.java | 1 + 4 files changed, 54 insertions(+), 12 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index 1a5c0edccd7a8..2f9f2e019867e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -171,6 +171,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Pattern; @@ -1140,7 +1142,8 @@ private Attribute resolveInsistAttribute(Attribute attribute, List ch // Field is partially unmapped. // TODO: Should the check for partially unmapped fields be done specific to each sub-query in a fork? if (resolvedCol instanceof FieldAttribute fa && indices.stream().anyMatch(r -> r.get().isPartiallyUnmappedField(fa.name()))) { - return fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa); + var esIndex = indices.stream().map(IndexResolution::get).filter(r -> r.isPartiallyUnmappedField(fa.name())).findFirst(); + return fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa, esIndex.get()); } // Either the field is mapped everywhere and we can just use the resolved column, or the INSIST clause isn't on top of a FROM @@ -1148,12 +1151,15 @@ private Attribute resolveInsistAttribute(Attribute attribute, List ch return resolvedCol; } - private static FieldAttribute invalidInsistAttribute(FieldAttribute fa) { + private static FieldAttribute invalidInsistAttribute(FieldAttribute fa, EsIndex esIndex) { var name = fa.name(); - EsField field = fa.field() instanceof InvalidMappedField imf - ? new InvalidMappedField(name, InvalidMappedField.makeErrorsMessageIncludingInsistKeyword(imf.getTypesToIndices())) - // FIXME(gal, NOCOMMIT) hard-coded for debugging - : new InvalidMappedField(name, Map.of("long", Set.of("sample_data"), "keyword", Set.of("no_mapping_sample_data"))); + Map> typesToIndices = new TreeMap<>(); + if (fa.field() instanceof InvalidMappedField imf) { + typesToIndices.putAll(imf.getTypesToIndices()); + } else { + typesToIndices.put(fa.dataType().typeName(), new TreeSet<>(esIndex.concreteQualifiedIndices())); + } + EsField field = InvalidMappedField.potentiallyUnmapped(name, typesToIndices); return new FieldAttribute(fa.source(), null, fa.qualifier(), name, field); } @@ -1184,7 +1190,12 @@ private static LogicalPlan resolvePartiallyMapped(LogicalPlan plan, AnalyzerCont } // Field is partially unmapped. if (indexResolutions.stream().anyMatch(r -> r.get().isPartiallyUnmappedField(fa.name()))) { - FieldAttribute newFA = fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa); + var esIndex = indexResolutions.stream() + .map(IndexResolution::get) + .filter(r -> r.isPartiallyUnmappedField(fa.name())) + .findFirst() + .get(); + FieldAttribute newFA = fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa, esIndex); insistedMap.put(fa, newFA); return newFA; } @@ -2237,8 +2248,12 @@ private Expression resolveConvertFunction(ConvertFunction convert, List> typesToIndices; + // FIXME(gal, NOCOMMIT) document + private final boolean isPotentiallyUnmapped; public InvalidMappedField(String name, String errorMessage, Map properties) { - this(name, errorMessage, properties, Map.of(), TimeSeriesFieldType.UNKNOWN); + this(name, errorMessage, properties, Map.of(), false, TimeSeriesFieldType.UNKNOWN); } public InvalidMappedField(String name, String errorMessage) { this(name, errorMessage, new TreeMap<>()); } + public InvalidMappedField(String name, Map> typesToIndices) { + this(name, makeErrorMessage(typesToIndices, false), new TreeMap<>(), typesToIndices, false, TimeSeriesFieldType.UNKNOWN); + } + /** * Constructor supporting union types, used in ES|QL. */ - public InvalidMappedField(String name, Map> typesToIndices) { - this(name, makeErrorMessage(typesToIndices, false), new TreeMap<>(), typesToIndices, TimeSeriesFieldType.UNKNOWN); + public static InvalidMappedField potentiallyUnmapped(String name, Map> typesToIndices) { + return new InvalidMappedField( + name, + makeErrorMessage(typesToIndices, true), + new TreeMap<>(), + typesToIndices, + true, + TimeSeriesFieldType.UNKNOWN + ); } private InvalidMappedField( @@ -52,11 +65,13 @@ private InvalidMappedField( String errorMessage, Map properties, Map> typesToIndices, + boolean isPotentiallyUnmapped, TimeSeriesFieldType type ) { super(name, DataType.UNSUPPORTED, properties, false, type); this.errorMessage = errorMessage; this.typesToIndices = typesToIndices; + this.isPotentiallyUnmapped = isPotentiallyUnmapped; } protected InvalidMappedField(StreamInput in) throws IOException { @@ -64,7 +79,9 @@ protected InvalidMappedField(StreamInput in) throws IOException { ((PlanStreamInput) in).readCachedString(), in.readString(), in.readImmutableMap(StreamInput::readString, EsField::readFrom), + // FIXME(gal, NOCOMMIT) Does this need to be protected with a version? Perhaps it's best to create a new type? Map.of(), + in.readBoolean(), readTimeSeriesFieldType(in) ); } @@ -78,6 +95,7 @@ public void writeContent(StreamOutput out) throws IOException { ((PlanStreamOutput) out).writeCachedString(getName()); out.writeString(errorMessage); out.writeMap(getProperties(), (o, x) -> x.writeTo(out)); + out.writeBoolean(isPotentiallyUnmapped); writeTimeSeriesFieldType(out); } @@ -119,6 +137,10 @@ public Map> getTypesToIndices() { return typesToIndices; } + public boolean isPotentiallyUnmapped() { + return isPotentiallyUnmapped; + } + public static String makeErrorsMessageIncludingInsistKeyword(Map> typesToIndices) { return makeErrorMessage(typesToIndices, true); } @@ -130,6 +152,7 @@ private static String makeErrorMessage(Map> typesToIndices, errorMessage.append(typesToIndices.size() + (isInsistKeywordOnlyKeyword ? 1 : 0)); errorMessage.append("] incompatible types: "); boolean first = true; + // FIXME(gal, NOCOMMIT) Rephrase to use LOAD if (isInsistKeywordOnlyKeyword) { first = false; errorMessage.append("[keyword] enforced by INSIST command"); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java index 8cc31d06bbf73..fd897b385aa21 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java @@ -227,7 +227,10 @@ private ValuesSourceReaderOperator.LoaderAndConverter blockLoaderAndConverter( return ValuesSourceReaderOperator.load(blockLoader); } // Use the fully qualified name `cluster:index-name` because multiple types are resolved on coordinator with the cluster prefix - Expression conversion = unionTypes.getConversionExpressionForIndex(indexName); + // FIXME(gal, NOCOMMIT) For unmapped indices, use the keyword conversion stored in the shard context hack + Expression conversion = shardContext instanceof DefaultShardContextForUnmappedField2 dsc + ? dsc.converted + : unionTypes.getConversionExpressionForIndex(indexName); if (conversion == null) { return ValuesSourceReaderOperator.LOAD_CONSTANT_NULLS; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java index b44b4a14f2746..589402719dbbb 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java @@ -500,6 +500,7 @@ private static EsField conflictingTypes(String name, String fullName, FieldCapab typesToIndices.computeIfAbsent(type.typeName(), _key -> new TreeSet<>()).add(ir.getIndexName()); } } + // FIXME(gal, NOCOMMIT) this also needs to take into account potentially unmapped fields! return new InvalidMappedField(name, typesToIndices); } From 0551fc7fe4457bbf876cfd4016fe2f1231827f39 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 11 Feb 2026 19:16:53 +0200 Subject: [PATCH 036/137] Even fewer hacks --- .../xpack/esql/analysis/Analyzer.java | 34 ++++--- .../esql/core/type/MultiTypeEsField.java | 38 ++++++-- .../xpack/esql/index/EsIndex.java | 12 ++- .../xpack/esql/index/IndexResolution.java | 2 +- .../planner/EsPhysicalOperationProviders.java | 93 ++++++------------- .../xpack/esql/session/EsqlSession.java | 2 +- .../xpack/esql/session/IndexResolver.java | 25 +++-- .../elasticsearch/xpack/esql/CsvTests.java | 22 +++-- .../esql/analysis/AnalyzerTestUtils.java | 8 +- .../xpack/esql/analysis/AnalyzerTests.java | 6 +- .../xpack/esql/index/EsIndexGenerator.java | 8 +- .../AbstractLogicalPlanOptimizerTests.java | 8 +- .../PromqlLogicalPlanOptimizerTests.java | 2 +- .../TimeSeriesBareAggregationsTests.java | 2 +- .../esql/type/MultiTypeEsFieldTests.java | 4 +- 15 files changed, 136 insertions(+), 130 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index 2f9f2e019867e..09c2e5b4d409b 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -14,6 +14,7 @@ import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.Page; +import org.elasticsearch.core.Nullable; import org.elasticsearch.index.IndexMode; import org.elasticsearch.logging.Logger; import org.elasticsearch.xpack.core.enrich.EnrichPolicy; @@ -1157,7 +1158,9 @@ private static FieldAttribute invalidInsistAttribute(FieldAttribute fa, EsIndex if (fa.field() instanceof InvalidMappedField imf) { typesToIndices.putAll(imf.getTypesToIndices()); } else { - typesToIndices.put(fa.dataType().typeName(), new TreeSet<>(esIndex.concreteQualifiedIndices())); + TreeSet indicesWithField = new TreeSet<>(esIndex.concreteQualifiedIndices()); + indicesWithField.removeAll(esIndex.getUnmappedIndices(fa.name())); + typesToIndices.put(fa.dataType().typeName(), indicesWithField); } EsField field = InvalidMappedField.potentiallyUnmapped(name, typesToIndices); return new FieldAttribute(fa.source(), null, fa.qualifier(), name, field); @@ -2248,13 +2251,12 @@ private Expression resolveConvertFunction(ConvertFunction convert, List typeResolutions + HashMap typeResolutions, + @Nullable Expression potentiallyUnmappedConversion ) { Map typesToConversionExpressions = new HashMap<>(); InvalidMappedField imf = (InvalidMappedField) fa.field(); @@ -2342,14 +2346,8 @@ private static MultiTypeEsField resolvedMultiTypeEsField( typesToConversionExpressions.put(typeName, typeResolutions.get(key)); } }); - // FIXME(gal, NOCOMMIT) more temp hacks - var result = MultiTypeEsField.resolveFrom(imf, typesToConversionExpressions); - result.potentiallyUnmappedExpression = typeResolutions.values() - .stream() - .filter(e -> ((ToDouble) e).field().dataType() == KEYWORD) - .findFirst() - .get(); - return result; + return MultiTypeEsField.resolveFrom(imf, typesToConversionExpressions) + .withPotentiallyUnmappedExpression(potentiallyUnmappedConversion); } private static boolean canConvertOriginalTypes(MultiTypeEsField multiTypeEsField, Set supportedTypes) { @@ -2459,7 +2457,7 @@ public LogicalPlan apply(LogicalPlan plan, AnalyzerContext context) { HashMap typeResolutions = new HashMap<>(); var convert = new ToDateNanos(f.source(), f, context.configuration()); imf.types().forEach(type -> typeResolutions(f, convert, type, imf, typeResolutions)); - var resolvedField = ResolveUnionTypes.resolvedMultiTypeEsField(f, typeResolutions); + var resolvedField = ResolveUnionTypes.resolvedMultiTypeEsField(f, typeResolutions, null); return new FieldAttribute( f.source(), f.parentName(), diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java index bafd1693d2761..d7560f7e4c404 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java @@ -32,19 +32,20 @@ public class MultiTypeEsField extends EsField { private final Map indexToConversionExpressions; - // FIXME(gal, NOCOMMIT) temp @Nullable - public Expression potentiallyUnmappedExpression = null; + private final Expression potentiallyUnmappedExpression; public MultiTypeEsField( String name, DataType dataType, boolean aggregatable, Map indexToConversionExpressions, - TimeSeriesFieldType timeSeriesFieldType + TimeSeriesFieldType timeSeriesFieldType, + @Nullable Expression potentiallyUnmappedExpression ) { super(name, dataType, Map.of(), aggregatable, timeSeriesFieldType); this.indexToConversionExpressions = indexToConversionExpressions; + this.potentiallyUnmappedExpression = potentiallyUnmappedExpression; } protected MultiTypeEsField(StreamInput in) throws IOException { @@ -53,7 +54,9 @@ protected MultiTypeEsField(StreamInput in) throws IOException { DataType.readFrom(in), in.readBoolean(), in.readImmutableMap(i -> i.readNamedWriteable(Expression.class)), - readTimeSeriesFieldType(in) + readTimeSeriesFieldType(in), + // FIXME(gal, NOCOMMIT) Does this need to be protected by a version check? + in.readNamedWriteable(Expression.class) ); } @@ -64,20 +67,36 @@ public void writeContent(StreamOutput out) throws IOException { out.writeBoolean(isAggregatable()); out.writeMap(getIndexToConversionExpressions(), (o, v) -> out.writeNamedWriteable(v)); writeTimeSeriesFieldType(out); + out.writeNamedWriteable(potentiallyUnmappedExpression); } public String getWriteableName() { return "MultiTypeEsField"; } + public @Nullable Expression getPotentiallyUnmappedExpression() { + return potentiallyUnmappedExpression; + } + public Map getIndexToConversionExpressions() { return indexToConversionExpressions; } - public Expression getConversionExpressionForIndex(String indexName) { + public @Nullable Expression getConversionExpressionForIndex(String indexName) { return indexToConversionExpressions.get(indexName); } + public MultiTypeEsField withPotentiallyUnmappedExpression(@Nullable Expression potentiallyUnmappedExpression) { + return new MultiTypeEsField( + getName(), + getDataType(), + isAggregatable(), + indexToConversionExpressions, + getTimeSeriesFieldType(), + potentiallyUnmappedExpression + ); + } + public static MultiTypeEsField resolveFrom( InvalidMappedField invalidMappedField, Map typesToConversionExpressions @@ -102,7 +121,8 @@ public static MultiTypeEsField resolveFrom( resolvedDataType, false, indexToConversionExpressions, - invalidMappedField.getTimeSeriesFieldType() + invalidMappedField.getTimeSeriesFieldType(), + null ); } @@ -112,14 +132,16 @@ public boolean equals(Object obj) { return false; } if (obj instanceof MultiTypeEsField other) { - return super.equals(other) && indexToConversionExpressions.equals(other.indexToConversionExpressions); + return super.equals(other) + && indexToConversionExpressions.equals(other.indexToConversionExpressions) + && Objects.equals(potentiallyUnmappedExpression, other.potentiallyUnmappedExpression); } return false; } @Override public int hashCode() { - return Objects.hash(super.hashCode(), indexToConversionExpressions); + return Objects.hash(super.hashCode(), indexToConversionExpressions, potentiallyUnmappedExpression); } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/index/EsIndex.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/index/EsIndex.java index dcd9a048a9f86..523a5c452530d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/index/EsIndex.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/index/EsIndex.java @@ -9,6 +9,7 @@ import org.elasticsearch.index.IndexMode; import org.elasticsearch.xpack.esql.core.type.EsField; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; @@ -19,17 +20,22 @@ public record EsIndex( Map indexNameWithModes, Map> originalIndices, // keyed by cluster alias Map> concreteIndices, // keyed by cluster alias - Set partiallyUnmappedFields + Map> fieldToUnmappedIndices // keyed by field name ) { public EsIndex { assert name != null; assert mapping != null; - assert partiallyUnmappedFields != null; + assert fieldToUnmappedIndices != null; + assert fieldToUnmappedIndices.values().stream().noneMatch(Set::isEmpty); } public boolean isPartiallyUnmappedField(String fieldName) { - return partiallyUnmappedFields.contains(fieldName); + return fieldToUnmappedIndices.containsKey(fieldName); + } + + public Set getUnmappedIndices(String fieldName) { + return fieldToUnmappedIndices.getOrDefault(fieldName, Collections.emptySet()); } public Set concreteQualifiedIndices() { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/index/IndexResolution.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/index/IndexResolution.java index 1bea2ad837c99..752e95bc1e20f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/index/IndexResolution.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/index/IndexResolution.java @@ -40,7 +40,7 @@ public static IndexResolution valid(EsIndex index) { } public static IndexResolution empty(String indexPattern) { - return valid(new EsIndex(indexPattern, Map.of(), Map.of(), Map.of(), Map.of(), Set.of())); + return valid(new EsIndex(indexPattern, Map.of(), Map.of(), Map.of(), Map.of(), Map.of())); } public static IndexResolution invalid(String invalid) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java index fd897b385aa21..c5498b8211979 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java @@ -200,40 +200,27 @@ private ValuesSourceReaderOperator.LoaderAndConverter blockLoaderAndConverter( Attribute attr, MappedFieldType.FieldExtractPreference fieldExtractPreference ) { - DefaultShardContext shardContext = (DefaultShardContext) shardContexts.get(shardId); + MultiTypeEsField unionTypes = findUnionTypes(attr); + DefaultShardContext shardContext = getShardContext(shardId, attr, unionTypes); + // Use the fully qualified name `cluster:index-name` because multiple types are resolved on coordinator with the cluster prefix String indexName = shardContext.ctx.getFullyQualifiedIndex().getName(); - if (attr instanceof FieldAttribute fa && fa.field() instanceof PotentiallyUnmappedKeywordEsField kf) { - shardContext = new DefaultShardContextForUnmappedField(shardContext, kf); - } - // Apply any block loader function if present - BlockLoaderFunctionConfig functionConfig = null; - if (attr instanceof FieldAttribute fieldAttr && fieldAttr.field() instanceof FunctionEsField functionEsField) { - functionConfig = functionEsField.functionConfig(); - } boolean isUnsupported = attr.dataType() == DataType.UNSUPPORTED; String fieldName = getFieldName(attr); - MultiTypeEsField unionTypes = findUnionTypes(attr); - // FIXME(gal, NOCOMMIT) More temp hacks - if (unionTypes != null && indexName.equals("no_mapping_sample_data")) { - shardContext = new DefaultShardContextForUnmappedField2( - shardContext, - new PotentiallyUnmappedKeywordEsField(fieldName), - unionTypes.potentiallyUnmappedExpression - ); - } + // Apply any block loader function if present + BlockLoaderFunctionConfig functionConfig = attr instanceof FieldAttribute fieldAttr + && fieldAttr.field() instanceof FunctionEsField functionEsField ? functionEsField.functionConfig() : null; BlockLoader blockLoader = shardContext.blockLoader(fieldName, isUnsupported, fieldExtractPreference, functionConfig); + // Happy path: No union types, no extra loaders, just load the values directly. if (unionTypes == null) { return ValuesSourceReaderOperator.load(blockLoader); } - // Use the fully qualified name `cluster:index-name` because multiple types are resolved on coordinator with the cluster prefix - // FIXME(gal, NOCOMMIT) For unmapped indices, use the keyword conversion stored in the shard context hack - Expression conversion = shardContext instanceof DefaultShardContextForUnmappedField2 dsc - ? dsc.converted - : unionTypes.getConversionExpressionForIndex(indexName); + Expression conversion = getConversion(indexName, unionTypes); + // Type-conflicted without a conversion function: return nulls for this field if (conversion == null) { return ValuesSourceReaderOperator.LOAD_CONSTANT_NULLS; } + // Special case for expressions that aren't plain type conversions. if (conversion instanceof BlockLoaderExpression ble) { BlockLoaderExpression.PushedBlockLoaderExpression e = ble.tryPushToFieldLoading(SearchStats.EMPTY); if (e != null) { @@ -245,45 +232,29 @@ private ValuesSourceReaderOperator.LoaderAndConverter blockLoaderAndConverter( return ValuesSourceReaderOperator.loadAndConvert(blockLoader, new TypeConverter((EsqlScalarFunction) conversion)); } - /** A hack to pretend an unmapped field still exists. */ - private static class DefaultShardContextForUnmappedField extends DefaultShardContext { - private static final FieldType UNMAPPED_FIELD_TYPE = new FieldType(KeywordFieldMapper.Defaults.FIELD_TYPE); - static { - UNMAPPED_FIELD_TYPE.setDocValuesType(DocValuesType.NONE); - UNMAPPED_FIELD_TYPE.setIndexOptions(IndexOptions.NONE); - UNMAPPED_FIELD_TYPE.setStored(false); - UNMAPPED_FIELD_TYPE.freeze(); - } - private final KeywordEsField unmappedEsField; - - DefaultShardContextForUnmappedField(DefaultShardContext ctx, PotentiallyUnmappedKeywordEsField unmappedEsField) { - super(ctx.index, ctx.releasable, ctx.ctx, ctx.aliasFilter); - this.unmappedEsField = unmappedEsField; + private DefaultShardContext getShardContext(int shardId, Attribute attr, MultiTypeEsField unionTypes) { + DefaultShardContext shardContext = (DefaultShardContext) shardContexts.get(shardId); + String indexName = shardContext.ctx.getFullyQualifiedIndex().getName(); + Expression conversion = unionTypes != null ? unionTypes.getConversionExpressionForIndex(indexName) : null; + if (attr instanceof FieldAttribute fa && fa.field() instanceof PotentiallyUnmappedKeywordEsField kf) { + return new DefaultShardContextForUnmappedField(shardContext, kf); } - - @Override - public @Nullable MappedFieldType fieldType(String name) { - var superResult = super.fieldType(name); - return superResult == null && name.equals(unmappedEsField.getName()) ? createUnmappedFieldType(name, this) : superResult; + if (unionTypes != null && conversion == null && unionTypes.getPotentiallyUnmappedExpression() != null) { + return new DefaultShardContextForUnmappedField(shardContext, new PotentiallyUnmappedKeywordEsField(getFieldName(attr))); } + return shardContext; + } - static MappedFieldType createUnmappedFieldType(String name, DefaultShardContext context) { - var builder = new KeywordFieldMapper.Builder(name, context.ctx.getIndexSettings()); - builder.docValues(false); - builder.indexed(false); - return new KeywordFieldMapper.KeywordFieldType( - name, - IndexType.terms(false, false), - new TextSearchInfo(UNMAPPED_FIELD_TYPE, builder.similarity(), Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER), - Lucene.KEYWORD_ANALYZER, - builder, - context.ctx.isSourceSynthetic() - ); - } + @Nullable + private Expression getConversion(String indexName, MultiTypeEsField unionTypes) { + Expression conversion = unionTypes.getConversionExpressionForIndex(indexName); + return conversion == null && unionTypes.getPotentiallyUnmappedExpression() != null + ? unionTypes.getPotentiallyUnmappedExpression() + : conversion; } - // FIXME(gal, NOCOMMIT) document, rename, whatever - private static class DefaultShardContextForUnmappedField2 extends DefaultShardContext { + /** A hack to pretend an unmapped field still exists. */ + private static class DefaultShardContextForUnmappedField extends DefaultShardContext { private static final FieldType UNMAPPED_FIELD_TYPE = new FieldType(KeywordFieldMapper.Defaults.FIELD_TYPE); static { UNMAPPED_FIELD_TYPE.setDocValuesType(DocValuesType.NONE); @@ -292,16 +263,10 @@ private static class DefaultShardContextForUnmappedField2 extends DefaultShardCo UNMAPPED_FIELD_TYPE.freeze(); } private final KeywordEsField unmappedEsField; - private final Expression converted; - DefaultShardContextForUnmappedField2( - DefaultShardContext ctx, - PotentiallyUnmappedKeywordEsField unmappedEsField, - Expression converted - ) { + DefaultShardContextForUnmappedField(DefaultShardContext ctx, PotentiallyUnmappedKeywordEsField unmappedEsField) { super(ctx.index, ctx.releasable, ctx.ctx, ctx.aliasFilter); this.unmappedEsField = unmappedEsField; - this.converted = converted; } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java index d24ee5c6c4a29..4bb1bebbcee7a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java @@ -960,7 +960,7 @@ private IndexResolution checkSingleIndex( Map.of(indexName, IndexMode.LOOKUP), Map.of(), Map.of(), - Set.of() + Map.of() ); return IndexResolution.valid(newIndex, newIndex.concreteQualifiedIndices(), lookupIndexResolution.failures()); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java index 589402719dbbb..41e51937ea843 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java @@ -50,6 +50,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; +import java.util.stream.Collectors; import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME; import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; @@ -300,13 +301,18 @@ public static IndexResolution mergedMappings( var collectedFieldCaps = collectFieldCaps(fieldsInfo.caps); Map fieldsCaps = collectedFieldCaps.fieldsCaps; Map indexMappingHashDuplicates = collectedFieldCaps.indexMappingHashDuplicates; + Map> fieldToMappedIndices = collectedFieldCaps.fieldToMappedIndices; + Set allIndexNames = fieldsInfo.caps.getIndexResponses() + .stream() + .map(FieldCapabilitiesIndexResponse::getIndexName) + .collect(Collectors.toSet()); // Build hierarchical fields - it's easier to do it in sorted order so the object fields come first. // TODO flattened is simpler - could we get away with that? String[] names = fieldsCaps.keySet().toArray(new String[0]); Arrays.sort(names); Map rootFields = new HashMap<>(); - Set partiallyUnmappedFields = new HashSet<>(); + Map> fieldToUnmappedIndices = new HashMap<>(); for (String name : names) { Map fields = rootFields; String fullName = name; @@ -343,10 +349,9 @@ public static IndexResolution mergedMappings( new HashMap<>() ); fields.put(name, field); - var isPartiallyUnmapped = fcs.size() + indexMappingHashDuplicates.getOrDefault(fieldCap.indexMappingHash, 0) < numberOfIndices; - if (isPartiallyUnmapped) { - partiallyUnmappedFields.add(fullName); - } + Set unmappedIndices = new TreeSet<>(allIndexNames); + unmappedIndices.removeAll(fieldToMappedIndices.getOrDefault(fullName, Set.of())); + fieldToUnmappedIndices.put(fullName, unmappedIndices); } boolean allEmpty = true; @@ -375,7 +380,7 @@ public static IndexResolution mergedMappings( // once all remotes support it (v9.3+) originalIndexExtractor.apply(indexPattern, fieldsInfo.caps), concreteIndices, - partiallyUnmappedFields + fieldToUnmappedIndices ); var failures = EsqlCCSUtils.groupFailuresPerCluster(fieldsInfo.caps.getFailures()); return IndexResolution.valid(index, indexNameWithModes.keySet(), failures); @@ -386,17 +391,20 @@ private record IndexFieldCapabilitiesWithSourceHash(List private record CollectedFieldCaps( Map fieldsCaps, // The map won't contain entries without duplicates, i.e., it's number of occurrences - 1. - Map indexMappingHashDuplicates + Map indexMappingHashDuplicates, + Map> fieldToMappedIndices ) {} private static CollectedFieldCaps collectFieldCaps(FieldCapabilitiesResponse fieldCapsResponse) { Map indexMappingHashToDuplicateCount = new HashMap<>(); Map fieldsCaps = new HashMap<>(); + Map> fieldToMappedIndices = new HashMap<>(); for (FieldCapabilitiesIndexResponse response : fieldCapsResponse.getIndexResponses()) { if (indexMappingHashToDuplicateCount.compute(response.getIndexMappingHash(), (k, v) -> v == null ? 1 : v + 1) > 1) { continue; } + String indexName = response.getIndexName(); for (IndexFieldCapabilities fc : response.get().values()) { if (fc.isMetadatafield()) { // ESQL builds the metadata fields if they are asked for without using the resolution. @@ -407,6 +415,7 @@ private static CollectedFieldCaps collectFieldCaps(FieldCapabilitiesResponse fie (_key) -> new IndexFieldCapabilitiesWithSourceHash(new ArrayList<>(), response.getIndexMappingHash()) ).fieldCapabilities; all.add(fc); + fieldToMappedIndices.computeIfAbsent(fc.name(), k -> new HashSet<>()).add(indexName); } } @@ -420,7 +429,7 @@ private static CollectedFieldCaps collectFieldCaps(FieldCapabilitiesResponse fie } } - return new CollectedFieldCaps(fieldsCaps, indexMappingHashToDuplicateCount); + return new CollectedFieldCaps(fieldsCaps, indexMappingHashToDuplicateCount, fieldToMappedIndices); } private static EsField createField( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java index 521f794233f25..6f7ba9e27b68c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java @@ -486,7 +486,7 @@ public static IndexResolution loadIndexResolution(CsvTestsDataLoader.MultiIndexT indexModes, Map.of(), Map.of(), - mergedMappings.partiallyUnmappedFields + mergedMappings.fieldToUnmappedIndices ) ); } @@ -524,10 +524,11 @@ private static Map createMappingForIndex(CsvTestsDataLoader.Tes record MappingPerIndex(String index, Map mapping) {} - record MergedResult(Map mapping, Set partiallyUnmappedFields) {} + record MergedResult(Map mapping, Map> fieldToUnmappedIndices) {} private static MergedResult mergeMappings(List mappingsPerIndex) { int numberOfIndices = mappingsPerIndex.size(); + Set allIndexNames = mappingsPerIndex.stream().map(MappingPerIndex::index).collect(Collectors.toSet()); Map> columnNamesToFieldByIndices = new HashMap<>(); for (var mappingPerIndex : mappingsPerIndex) { for (var entry : mappingPerIndex.mapping().entrySet()) { @@ -537,15 +538,20 @@ private static MergedResult mergeMappings(List mappingsPerIndex } } - var partiallyUnmappedFields = columnNamesToFieldByIndices.entrySet() - .stream() - .filter(e -> e.getValue().size() < numberOfIndices) - .map(Map.Entry::getKey) - .collect(Collectors.toSet()); + Map> fieldToUnmappedIndices = new HashMap<>(); + for (var e : columnNamesToFieldByIndices.entrySet()) { + if (e.getValue().size() < numberOfIndices) { + String fieldName = e.getKey(); + Set mappedIndices = e.getValue().keySet(); + Set unmappedIndices = new HashSet<>(allIndexNames); + unmappedIndices.removeAll(mappedIndices); + fieldToUnmappedIndices.put(fieldName, unmappedIndices); + } + } var mappings = columnNamesToFieldByIndices.entrySet() .stream() .collect(Collectors.toMap(Map.Entry::getKey, e -> mergeFields(e.getKey(), e.getValue()))); - return new MergedResult(mappings, partiallyUnmappedFields); + return new MergedResult(mappings, fieldToUnmappedIndices); } private static EsField mergeFields(String index, Map columnNameToField) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java index 23e6d543c6fb3..162bec34576d3 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java @@ -229,7 +229,7 @@ private static Map indexResolutions(@Nullable Str } var indexResolution = IndexResolution.valid( - new EsIndex(indexName, MAPPING_BASIC_RESOLUTION, Map.of(indexName, IndexMode.STANDARD), Map.of(), Map.of(), Set.of()) + new EsIndex(indexName, MAPPING_BASIC_RESOLUTION, Map.of(indexName, IndexMode.STANDARD), Map.of(), Map.of(), Map.of()) ); return Map.of(new IndexPattern(Source.EMPTY, indexName), indexResolution); } @@ -270,7 +270,7 @@ public static UnresolvedRelation unresolvedRelation(String index) { public static IndexResolution loadMapping(String resource, String indexName, IndexMode indexMode) { return IndexResolution.valid( - new EsIndex(indexName, EsqlTestUtils.loadMapping(resource), Map.of(indexName, indexMode), Map.of(), Map.of(), Set.of()) + new EsIndex(indexName, EsqlTestUtils.loadMapping(resource), Map.of(indexName, indexMode), Map.of(), Map.of(), Map.of()) ); } @@ -388,7 +388,7 @@ public static Map defaultSubqueryResolution() { Map.of(NO_FIELDS_INDEX, IndexMode.STANDARD), Map.of("", List.of(NO_FIELDS_INDEX)), Map.of("", List.of(NO_FIELDS_INDEX)), - Set.of() + Map.of() ); return Map.of( new IndexPattern(Source.EMPTY, "languages"), @@ -495,7 +495,7 @@ public static IndexResolution indexWithDateDateNanosUnionType() { Map.of("index1", IndexMode.STANDARD, "index2", IndexMode.STANDARD, "index3", IndexMode.STANDARD), Map.of(), Map.of(), - Set.of() + Map.of() ); return IndexResolution.valid(index); } 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 f59970e8fa493..c6001fa926b4a 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 @@ -4469,7 +4469,7 @@ public void testProjectionForUnionTypeResolution() { Map.of("union_index_1", IndexMode.STANDARD, "union_index_2", IndexMode.STANDARD), Map.of(), Map.of(), - Set.of() + Map.of() ); IndexResolution resolution = IndexResolution.valid(index); Analyzer analyzer = analyzer(resolution); @@ -4513,7 +4513,7 @@ public void testExplicitRetainOriginalFieldWithCast() { Map.of("test1", IndexMode.STANDARD, "test2", IndexMode.STANDARD), Map.of(), Map.of(), - Set.of() + Map.of() ); IndexResolution resolution = IndexResolution.valid(index); Analyzer analyzer = analyzer(resolution); @@ -4764,7 +4764,7 @@ public void testImplicitCastingForAggregateMetricDouble() { Map.of("k8s", IndexMode.TIME_SERIES, "k8s-downsampled", IndexMode.TIME_SERIES), Map.of(), Map.of(), - Set.of() + Map.of() ); var analyzer = new Analyzer( testAnalyzerContext( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/index/EsIndexGenerator.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/index/EsIndexGenerator.java index 9e10fa2eb2cc9..d59b82f8b905c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/index/EsIndexGenerator.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/index/EsIndexGenerator.java @@ -26,19 +26,19 @@ public class EsIndexGenerator { public static EsIndex esIndex(String name) { - return new EsIndex(name, Map.of(), Map.of(), Map.of(), Map.of(), Set.of()); + return new EsIndex(name, Map.of(), Map.of(), Map.of(), Map.of(), Map.of()); } public static EsIndex esIndex(String name, Map mapping) { - return new EsIndex(name, mapping, Map.of(), Map.of(), Map.of(), Set.of()); + return new EsIndex(name, mapping, Map.of(), Map.of(), Map.of(), Map.of()); } public static EsIndex esIndex(String name, Map mapping, Map indexNameWithModes) { - return new EsIndex(name, mapping, indexNameWithModes, Map.of(), Map.of(), Set.of()); + return new EsIndex(name, mapping, indexNameWithModes, Map.of(), Map.of(), Map.of()); } public static EsIndex randomEsIndex() { - return new EsIndex(randomIdentifier(), randomMapping(), randomIndexNameWithModes(), Map.of(), Map.of(), Set.of()); + return new EsIndex(randomIdentifier(), randomMapping(), randomIndexNameWithModes(), Map.of(), Map.of(), Map.of()); } public static Map randomMapping() { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/AbstractLogicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/AbstractLogicalPlanOptimizerTests.java index 0e31996ed901c..99e5b5f4bea87 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/AbstractLogicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/AbstractLogicalPlanOptimizerTests.java @@ -207,7 +207,7 @@ public static void init() { Map.of("test1", IndexMode.STANDARD, "test2", IndexMode.STANDARD), Map.of(), Map.of(), - Set.of("partial_type_keyword") + Map.of("partial_type_keyword", Set.of("test2")) ); multiIndexAnalyzer = new Analyzer( testAnalyzerContext( @@ -232,7 +232,7 @@ public static void init() { Map.of("test1", IndexMode.STANDARD, "test2", IndexMode.STANDARD), Map.of(), Map.of(), - Set.of() + Map.of() ); unionIndexAnalyzer = new Analyzer( testAnalyzerContext( @@ -253,7 +253,7 @@ public static void init() { Map.of("sample_data", IndexMode.STANDARD), Map.of(), Map.of(), - Set.of() + Map.of() ); sampleDataIndexAnalyzer = new Analyzer( testAnalyzerContext( @@ -286,7 +286,7 @@ public static void init() { Map.of("base_conversion", IndexMode.STANDARD), Map.of(), Map.of(), - Set.of() + Map.of() ); baseConversionAnalyzer = new Analyzer( testAnalyzerContext( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/PromqlLogicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/PromqlLogicalPlanOptimizerTests.java index 2e204f50963c4..d9c37697dec27 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/PromqlLogicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/PromqlLogicalPlanOptimizerTests.java @@ -89,7 +89,7 @@ public class PromqlLogicalPlanOptimizerTests extends AbstractLogicalPlanOptimize public static void initTest() { var timeSeriesMapping = loadMapping("k8s-mappings.json"); var timeSeriesIndex = IndexResolution.valid( - new EsIndex("k8s", timeSeriesMapping, Map.of("k8s", IndexMode.TIME_SERIES), Map.of(), Map.of(), Set.of()) + new EsIndex("k8s", timeSeriesMapping, Map.of("k8s", IndexMode.TIME_SERIES), Map.of(), Map.of(), Map.of()) ); tsAnalyzer = new Analyzer( new AnalyzerContext( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/TimeSeriesBareAggregationsTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/TimeSeriesBareAggregationsTests.java index 97d9677518b3d..af1b8c0b867e2 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/TimeSeriesBareAggregationsTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/TimeSeriesBareAggregationsTests.java @@ -50,7 +50,7 @@ public class TimeSeriesBareAggregationsTests extends AbstractLogicalPlanOptimize @BeforeClass public static void initK8s() { mappingK8s = loadMapping("k8s-mappings.json"); - EsIndex k8sIndex = new EsIndex("k8s", mappingK8s, Map.of("k8s", IndexMode.TIME_SERIES), Map.of(), Map.of(), Set.of()); + EsIndex k8sIndex = new EsIndex("k8s", mappingK8s, Map.of("k8s", IndexMode.TIME_SERIES), Map.of(), Map.of(), Map.of()); IndexResolution indexResolution = IndexResolution.valid(k8sIndex); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/MultiTypeEsFieldTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/MultiTypeEsFieldTests.java index 4529eb495acaf..d7d0f93a41f78 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/MultiTypeEsFieldTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/MultiTypeEsFieldTests.java @@ -65,7 +65,7 @@ protected MultiTypeEsField createTestInstance() { DataType toType = toString ? DataType.KEYWORD : dataType; Map indexToConvertExpressions = randomConvertExpressions(name, toString, dataType); EsField.TimeSeriesFieldType tsType = randomFrom(EsField.TimeSeriesFieldType.values()); - return new MultiTypeEsField(name, toType, false, indexToConvertExpressions, tsType); + return new MultiTypeEsField(name, toType, false, indexToConvertExpressions, tsType, null); } @Override @@ -81,7 +81,7 @@ protected MultiTypeEsField mutateInstance(MultiTypeEsField instance) throws IOEx case 3 -> tsType = randomValueOtherThan(tsType, () -> randomFrom(EsField.TimeSeriesFieldType.values())); default -> throw new IllegalArgumentException(); } - return new MultiTypeEsField(name, dataType, false, indexToConvertExpressions, tsType); + return new MultiTypeEsField(name, dataType, false, indexToConvertExpressions, tsType, null); } @Override From b6ff758feaacf869dad9a43fd5d3cf9b17db7ddf Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 11 Feb 2026 22:52:28 +0200 Subject: [PATCH 037/137] Fix bugs, undo SET hardcode --- .../elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java | 3 --- .../org/elasticsearch/xpack/esql/session/IndexResolver.java | 4 +++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java index a6d5dfa6fe30b..fdddd59d84255 100644 --- a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java +++ b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java @@ -371,9 +371,6 @@ protected void doTest() throws Throwable { } protected final void doTest(String query) throws Throwable { - if (query.toUpperCase().startsWith("SET") == false) { - query = "SET unmapped_fields=\"load\"; " + query; - } RequestObjectBuilder builder = new RequestObjectBuilder(randomFrom(XContentType.values())); if (query.toUpperCase(Locale.ROOT).contains("LOOKUP_\uD83D\uDC14")) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java index 41e51937ea843..ed7cdc70b0952 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java @@ -351,7 +351,9 @@ public static IndexResolution mergedMappings( fields.put(name, field); Set unmappedIndices = new TreeSet<>(allIndexNames); unmappedIndices.removeAll(fieldToMappedIndices.getOrDefault(fullName, Set.of())); - fieldToUnmappedIndices.put(fullName, unmappedIndices); + if (unmappedIndices.isEmpty() == false) { + fieldToUnmappedIndices.put(fullName, unmappedIndices); + } } boolean allEmpty = true; From 6921a2a2d70dd87e4f5e545a77c762d457e05222 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 11 Feb 2026 23:37:05 +0200 Subject: [PATCH 038/137] Fix serialization --- .../xpack/esql/core/type/MultiTypeEsField.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java index d7560f7e4c404..dcca3cda55188 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java @@ -56,7 +56,7 @@ protected MultiTypeEsField(StreamInput in) throws IOException { in.readImmutableMap(i -> i.readNamedWriteable(Expression.class)), readTimeSeriesFieldType(in), // FIXME(gal, NOCOMMIT) Does this need to be protected by a version check? - in.readNamedWriteable(Expression.class) + in.readBoolean() ? in.readNamedWriteable(Expression.class) : null ); } @@ -67,7 +67,12 @@ public void writeContent(StreamOutput out) throws IOException { out.writeBoolean(isAggregatable()); out.writeMap(getIndexToConversionExpressions(), (o, v) -> out.writeNamedWriteable(v)); writeTimeSeriesFieldType(out); - out.writeNamedWriteable(potentiallyUnmappedExpression); + if (potentiallyUnmappedExpression == null) { + out.writeBoolean(false); + } else { + out.writeBoolean(true); + out.writeNamedWriteable(potentiallyUnmappedExpression); + } } public String getWriteableName() { From 1bdd76487918e8cb5969f3966631784dc6b09850 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 12 Feb 2026 12:31:16 +0200 Subject: [PATCH 039/137] Fix CSVTests --- .../esql/planner/TestPhysicalOperationProviders.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java index da247eb443ecc..f962c66e04046 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java @@ -312,7 +312,7 @@ private Block getBlockForMultiType( MultiTypeEsField multiTypeEsField, TestBlockCopier blockCopier ) { - var conversion = (AbstractConvertFunction) multiTypeEsField.getConversionExpressionForIndex(getIndexPage(indexDoc).index); + var conversion = getConversion(multiTypeEsField, getIndexPage(indexDoc)); if (conversion == null) { return getNullsBlock(indexDoc); } @@ -326,6 +326,15 @@ private Block getBlockForMultiType( }; } + @Nullable + private static AbstractConvertFunction getConversion(MultiTypeEsField multiTypeEsField, IndexPage indexPage) { + var conversion = (AbstractConvertFunction) multiTypeEsField.getConversionExpressionForIndex(indexPage.index); + boolean isPotentiallyUnmapped = conversion == null + && multiTypeEsField.getPotentiallyUnmappedExpression() != null + && indexPage.mappedFields().contains(multiTypeEsField.getName()) == false; + return isPotentiallyUnmapped ? (AbstractConvertFunction) multiTypeEsField.getPotentiallyUnmappedExpression() : conversion; + } + private IndexPage getIndexPage(DocBlock indexDoc) { return indexPages.get(indexDoc.asVector().shards().getInt(0)); } From d7605d37456cca778dd3cd6cce4df61d188be495 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 12 Feb 2026 13:23:05 +0200 Subject: [PATCH 040/137] Even fewer hacks --- .../rules/logical/local/ReplaceFieldWithConstantOrNull.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java index 6d6a57ad15c12..78e4cb7c6456e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java @@ -72,7 +72,7 @@ else if (esRelation.indexMode() == IndexMode.STANDARD) { // Do not use the attribute name, this can deviate from the field name for union types; use fieldName() instead. // Also retain fields from lookup indices because we do not have stats for these. Predicate shouldBeRetained = f -> f.field() instanceof PotentiallyUnmappedKeywordEsField - || f.field() instanceof MultiTypeEsField // FIXME(gal, NOCOMMIT) More temp hacks + || (f.field() instanceof MultiTypeEsField mf && mf.getPotentiallyUnmappedExpression() != null) // The source (or doc) field is added to the relation output as a hack to enable late materialization in the reduce driver. || EsQueryExec.isDocAttribute(f) || localLogicalOptimizerContext.searchStats().exists(f.fieldName()) From 6204995c25bd1f7d149ddc54783b1385797f08e0 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 12 Feb 2026 21:15:33 +0200 Subject: [PATCH 041/137] Added test, remove fixme --- .../src/main/resources/unmapped-load.csv-spec | 52 +++++++++++++++---- .../main/resources/unmapped-nullify.csv-spec | 50 +++++++++--------- .../xpack/esql/session/IndexResolver.java | 1 - 3 files changed, 67 insertions(+), 36 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index c766aef112dae..85502784e573f 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -787,28 +787,60 @@ sample_data | Connected to 10.1.0.2 no_mapping_sample_data | Connected to 10.1.0.2! ; -# Type resolution bug: event_duration is long in sample_data, unmapped (loaded) in no_mapping_sample_data; cast to DOUBLE fails to resolve -unmappedLoadEventDurationCastToDouble +partiallyUnmappedNonKeyword required_capability: unmapped_fields -required_capability: optional_fields +required_capability: index_metadata_field SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data METADATA _index -| EVAL event_duration = event_duration :: DOUBLE +| EVAL event_duration = event_duration::DOUBLE | KEEP _index, event_duration -| SORT event_duration, _index DESC -| LIMIT 10 +| SORT _index, event_duration ; _index:keyword | event_duration:double no_mapping_sample_data | 725447.0 -sample_data | 725448.0 no_mapping_sample_data | 1232381.0 -sample_data | 1232382.0 no_mapping_sample_data | 1756466.0 -sample_data | 1756467.0 no_mapping_sample_data | 2764888.0 -sample_data | 2764889.0 no_mapping_sample_data | 3450232.0 +no_mapping_sample_data | 5033754.0 +no_mapping_sample_data | 8268152.0 +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +; + +partiallyUnmappedNonKeywordMultiType +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data, employees METADATA _index +| EVAL event_duration = event_duration::DOUBLE +| KEEP _index, event_duration +| SORT _index DESC, event_duration +| LIMIT 18 +; + +_index:keyword | event_duration:double +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +no_mapping_sample_data | 725447.0 +no_mapping_sample_data | 1232381.0 +no_mapping_sample_data | 1756466.0 +no_mapping_sample_data | 2764888.0 +no_mapping_sample_data | 3450232.0 +no_mapping_sample_data | 5033754.0 +no_mapping_sample_data | 8268152.0 +employees | null +employees | null +employees | null +employees | null ; diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec index 48f0e0db265fa..6601f2dfdd467 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec @@ -499,7 +499,7 @@ x:integer |does_not_exist:null |y:keyword | language_name:keyword 1 |null |null |null ; -partiallyUnmappedKeywordMultiIndex +partiallyUnmappedKeyword required_capability: optional_fields_nullify_tech_preview required_capability: index_metadata_field @@ -526,35 +526,35 @@ sample_data | 2023-10-23T12:27:28.948Z | Connected to 10.1.0.2 sample_data | 2023-10-23T12:15:03.360Z | Connected to 10.1.0.3 ; -partiallyUnmappedNonKeywordMultiIndexCast +partiallyUnmappedNonKeyword required_capability: optional_fields_nullify_tech_preview required_capability: index_metadata_field SET unmapped_fields="nullify"\; FROM sample_data, no_mapping_sample_data METADATA _index -| EVAL duration = event_duration::DOUBLE -| KEEP _index, @timestamp, duration -| SORT _index, @timestamp DESC -; - -_index:keyword | @timestamp:date | duration:double -no_mapping_sample_data | null | null -no_mapping_sample_data | null | null -no_mapping_sample_data | null | null -no_mapping_sample_data | null | null -no_mapping_sample_data | null | null -no_mapping_sample_data | null | null -no_mapping_sample_data | null | null -sample_data | 2023-10-23T13:55:01.543Z | 1756467.0 -sample_data | 2023-10-23T13:53:55.832Z | 5033755.0 -sample_data | 2023-10-23T13:52:55.015Z | 8268153.0 -sample_data | 2023-10-23T13:51:54.732Z | 725448.0 -sample_data | 2023-10-23T13:33:34.937Z | 1232382.0 -sample_data | 2023-10-23T12:27:28.948Z | 2764889.0 -sample_data | 2023-10-23T12:15:03.360Z | 3450233.0 -; - -partiallyUnmappedMixedTypesMultiIndexCast +| EVAL event_duration = event_duration::DOUBLE +| KEEP _index, event_duration +| SORT _index, event_duration +; + +_index:keyword | event_duration:double +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +; + +partiallyUnmappedMixedTypes required_capability: optional_fields_nullify_tech_preview required_capability: index_metadata_field diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java index ed7cdc70b0952..446c0633d6562 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java @@ -511,7 +511,6 @@ private static EsField conflictingTypes(String name, String fullName, FieldCapab typesToIndices.computeIfAbsent(type.typeName(), _key -> new TreeSet<>()).add(ir.getIndexName()); } } - // FIXME(gal, NOCOMMIT) this also needs to take into account potentially unmapped fields! return new InvalidMappedField(name, typesToIndices); } From 9cceee566346b8613bcfa79763c093a101d589d7 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 12 Feb 2026 21:29:00 +0200 Subject: [PATCH 042/137] Add another test --- .../src/main/resources/unmapped-load.csv-spec | 37 ++++++++++++++++++- .../main/resources/unmapped-nullify.csv-spec | 6 +-- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index 85502784e573f..b0c1cceac6fac 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -815,7 +815,7 @@ sample_data | 5033755.0 sample_data | 8268153.0 ; -partiallyUnmappedNonKeywordMultiType +partiallyUnmappedNonKeywordNoExistence SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data, employees METADATA _index | EVAL event_duration = event_duration::DOUBLE @@ -844,3 +844,38 @@ employees | null employees | null employees | null ; + +partiallyUnmappedMixedTypes +required_capability: unmapped_fields +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data, logs, no_mapping_sample_data METADATA _index +| EVAL message = message::KEYWORD, @timestamp = @timestamp :: date +| KEEP _index, @timestamp, message +| SORT _index, @timestamp DESC +; + +_index:keyword | @timestamp:date | message:keyword +logs | 2023-10-23T13:57:01.544Z | Running cats (cycle 3) +logs | 2023-10-23T13:56:01.544Z | Running cats (cycle 2) +logs | 2023-10-23T13:56:01.543Z | No response +logs | 2023-10-23T13:55:01.546Z | More java stuff +logs | 2023-10-23T13:55:01.545Z | Doing java stuff for 192.168.86.038 +logs | 2023-10-23T13:55:01.544Z | Running cats (cycle 1) +logs | 2023-10-23T13:55:01.543Z | Pinging 192.168.86.046 +no_mapping_sample_data | 2024-10-23T13:55:01.543Z | null +no_mapping_sample_data | 2024-10-23T13:53:55.832Z | null +no_mapping_sample_data | 2024-10-23T13:52:55.015Z | null +no_mapping_sample_data | 2024-10-23T13:51:54.732Z | null +no_mapping_sample_data | 2024-10-23T13:33:34.937Z | null +no_mapping_sample_data | 2024-10-23T12:27:28.948Z | null +no_mapping_sample_data | 2024-10-23T12:15:03.360Z | null +sample_data | 2023-10-23T13:55:01.543Z | Connected to 10.1.0.1 +sample_data | 2023-10-23T13:53:55.832Z | Connection error +sample_data | 2023-10-23T13:52:55.015Z | Connection error +sample_data | 2023-10-23T13:51:54.732Z | Connection error +sample_data | 2023-10-23T13:33:34.937Z | Disconnected +sample_data | 2023-10-23T12:27:28.948Z | Connected to 10.1.0.2 +sample_data | 2023-10-23T12:15:03.360Z | Connected to 10.1.0.3 +; diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec index 6601f2dfdd467..c885e94cddda6 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec @@ -560,12 +560,12 @@ required_capability: index_metadata_field SET unmapped_fields="nullify"\; FROM sample_data, logs, no_mapping_sample_data METADATA _index -| EVAL msg = message::KEYWORD -| KEEP _index, @timestamp, msg +| EVAL message = message::KEYWORD +| KEEP _index, @timestamp, message | SORT _index, @timestamp DESC ; -_index:keyword | @timestamp:date | msg:keyword +_index:keyword | @timestamp:date | message:keyword logs | 2023-10-23T13:57:01.544Z | Running cats (cycle 3) logs | 2023-10-23T13:56:01.544Z | Running cats (cycle 2) logs | 2023-10-23T13:56:01.543Z | No response From 1cec9f129b5b78e7a869e3a1b1f09cac6c37d596 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Fri, 13 Feb 2026 00:12:39 +0200 Subject: [PATCH 043/137] Fix failing CSV test --- .../xpack/esql/planner/TestPhysicalOperationProviders.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java index f962c66e04046..22aebc93cebc6 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java @@ -319,6 +319,11 @@ private Block getBlockForMultiType( return switch (extractBlockForSingleDoc(indexDoc, ((FieldAttribute) conversion.field()).fieldName().string(), blockCopier)) { case BlockResultMissing unused -> getNullsBlock(indexDoc); case BlockResultSuccess success -> { + if (success.block.elementType() != PlannerUtils.toElementType(conversion.field().dataType().widenSmallNumeric()) + && success.block.elementType() == PlannerUtils.toElementType(conversion.dataType().widenSmallNumeric())) { + // Block is already in the correct type, we can skip the conversion. + yield success.block; + } try (var converter = new TypeConverter(conversion).build(context)) { yield converter.convert(success.block); } From 19bf3cdc3705af6ef5c27f559b2f1e497aadd96d Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 23 Feb 2026 19:44:54 +0200 Subject: [PATCH 044/137] Some manual refactors --- .../referable/esql_unampped_fields_load.csv | 1 + .../resources/transport/upper_bounds/9.4.csv | 2 +- .../src/main/resources/unmapped-load.csv-spec | 2 +- .../xpack/esql/analysis/Analyzer.java | 23 +++++++++---------- .../esql/core/type/InvalidMappedField.java | 17 +++++--------- .../esql/core/type/MultiTypeEsField.java | 20 ++++++++-------- .../elasticsearch/xpack/esql/CsvTests.java | 15 ++++++------ 7 files changed, 39 insertions(+), 41 deletions(-) create mode 100644 server/src/main/resources/transport/definitions/referable/esql_unampped_fields_load.csv diff --git a/server/src/main/resources/transport/definitions/referable/esql_unampped_fields_load.csv b/server/src/main/resources/transport/definitions/referable/esql_unampped_fields_load.csv new file mode 100644 index 0000000000000..f43c057011643 --- /dev/null +++ b/server/src/main/resources/transport/definitions/referable/esql_unampped_fields_load.csv @@ -0,0 +1 @@ +9271000 diff --git a/server/src/main/resources/transport/upper_bounds/9.4.csv b/server/src/main/resources/transport/upper_bounds/9.4.csv index 68595a37842bb..798c46baec462 100644 --- a/server/src/main/resources/transport/upper_bounds/9.4.csv +++ b/server/src/main/resources/transport/upper_bounds/9.4.csv @@ -1 +1 @@ -bulk_by_scroll_request_includes_relocation_field,9270000 +esql_unampped_fields_load,9271000 diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index b0c1cceac6fac..8fffa7d85f923 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -856,7 +856,7 @@ FROM sample_data, logs, no_mapping_sample_data METADATA _index | SORT _index, @timestamp DESC ; -_index:keyword | @timestamp:date | message:keyword +_index:keyword | @timestamp:date | message:keyword logs | 2023-10-23T13:57:01.544Z | Running cats (cycle 3) logs | 2023-10-23T13:56:01.544Z | Running cats (cycle 2) logs | 2023-10-23T13:56:01.543Z | No response diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index 09c2e5b4d409b..0768bb1d01412 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -1143,8 +1143,7 @@ private Attribute resolveInsistAttribute(Attribute attribute, List ch // Field is partially unmapped. // TODO: Should the check for partially unmapped fields be done specific to each sub-query in a fork? if (resolvedCol instanceof FieldAttribute fa && indices.stream().anyMatch(r -> r.get().isPartiallyUnmappedField(fa.name()))) { - var esIndex = indices.stream().map(IndexResolution::get).filter(r -> r.isPartiallyUnmappedField(fa.name())).findFirst(); - return fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa, esIndex.get()); + return fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa, indices); } // Either the field is mapped everywhere and we can just use the resolved column, or the INSIST clause isn't on top of a FROM @@ -1152,8 +1151,13 @@ private Attribute resolveInsistAttribute(Attribute attribute, List ch return resolvedCol; } - private static FieldAttribute invalidInsistAttribute(FieldAttribute fa, EsIndex esIndex) { - var name = fa.name(); + private static FieldAttribute invalidInsistAttribute(FieldAttribute fa, List indexResolutions) { + String name = fa.name(); + EsIndex esIndex = indexResolutions.stream() + .map(IndexResolution::get) + .filter(r -> r.isPartiallyUnmappedField(name)) + .findFirst() + .orElseThrow(); Map> typesToIndices = new TreeMap<>(); if (fa.field() instanceof InvalidMappedField imf) { typesToIndices.putAll(imf.getTypesToIndices()); @@ -1185,20 +1189,15 @@ private static LogicalPlan resolvePartiallyMapped(LogicalPlan plan, AnalyzerCont Map insistedMap = new HashMap<>(); var transformed = plan.transformExpressionsOnly(FieldAttribute.class, fa -> { var esField = fa.field(); - var isInsisted = esField instanceof PotentiallyUnmappedKeywordEsField || esField instanceof InvalidMappedField; - if (isInsisted == false) { + var isPotentiallyUnmapped = esField instanceof PotentiallyUnmappedKeywordEsField || esField instanceof InvalidMappedField; + if (isPotentiallyUnmapped == false) { var existing = insistedMap.get(fa); if (existing != null) { // field shows up multiple times in the node; return first processing return existing; } // Field is partially unmapped. if (indexResolutions.stream().anyMatch(r -> r.get().isPartiallyUnmappedField(fa.name()))) { - var esIndex = indexResolutions.stream() - .map(IndexResolution::get) - .filter(r -> r.isPartiallyUnmappedField(fa.name())) - .findFirst() - .get(); - FieldAttribute newFA = fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa, esIndex); + FieldAttribute newFA = fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa, indexResolutions); insistedMap.put(fa, newFA); return newFA; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/InvalidMappedField.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/InvalidMappedField.java index 3689e60d07ba0..a6779502ace8e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/InvalidMappedField.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/InvalidMappedField.java @@ -21,17 +21,18 @@ import java.util.stream.Collectors; /** - * Representation of field mapped differently across indices. + * Representation of field mapped differently across indices; or being potentially unmapped in some, in which case it is treated as + * {@link DataType#KEYWORD} in the indices where it is unmapped. * Used during mapping discovery only. - * Note that the field typesToIndices is not serialized because that information is + * Note that the fields typesToIndices and isPotentiallyUnmapped are not serialized because that information is * not required through the cluster, only surviving as long as the Analyser phase of query planning. - * It is used specifically for the 'union types' feature in ES|QL. + * It is used specifically for the 'union types' and 'unmapped fields' feature in ES|QL. */ public class InvalidMappedField extends EsField { private final String errorMessage; private final Map> typesToIndices; - // FIXME(gal, NOCOMMIT) document + // Marks the field as being unmapped in some indices. private final boolean isPotentiallyUnmapped; public InvalidMappedField(String name, String errorMessage, Map properties) { @@ -79,9 +80,8 @@ protected InvalidMappedField(StreamInput in) throws IOException { ((PlanStreamInput) in).readCachedString(), in.readString(), in.readImmutableMap(StreamInput::readString, EsField::readFrom), - // FIXME(gal, NOCOMMIT) Does this need to be protected with a version? Perhaps it's best to create a new type? Map.of(), - in.readBoolean(), + false, readTimeSeriesFieldType(in) ); } @@ -95,7 +95,6 @@ public void writeContent(StreamOutput out) throws IOException { ((PlanStreamOutput) out).writeCachedString(getName()); out.writeString(errorMessage); out.writeMap(getProperties(), (o, x) -> x.writeTo(out)); - out.writeBoolean(isPotentiallyUnmapped); writeTimeSeriesFieldType(out); } @@ -141,10 +140,6 @@ public boolean isPotentiallyUnmapped() { return isPotentiallyUnmapped; } - public static String makeErrorsMessageIncludingInsistKeyword(Map> typesToIndices) { - return makeErrorMessage(typesToIndices, true); - } - private static String makeErrorMessage(Map> typesToIndices, boolean includeInsistKeyword) { StringBuilder errorMessage = new StringBuilder(); var isInsistKeywordOnlyKeyword = includeInsistKeyword && typesToIndices.containsKey(DataType.KEYWORD.typeName()) == false; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java index dcca3cda55188..ee729aa233a46 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java @@ -7,9 +7,11 @@ package org.elasticsearch.xpack.esql.core.type; +import org.elasticsearch.TransportVersion; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.core.Nullable; +import org.elasticsearch.core.Strings; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput; import org.elasticsearch.xpack.esql.io.stream.PlanStreamOutput; @@ -30,8 +32,14 @@ * type conversion is done at the data node level. */ public class MultiTypeEsField extends EsField { + private static final TransportVersion UNMAPPED_FIELDS_LOAD = TransportVersion.fromName("esql_unampped_fields_load"); private final Map indexToConversionExpressions; + + /** + * If this is not {@code null}, then this expression should be used to convert the field value in case the field is not mapped in an + * index, to convert the {@link DataType#KEYWORD} to the target type. + */ @Nullable private final Expression potentiallyUnmappedExpression; @@ -55,8 +63,7 @@ protected MultiTypeEsField(StreamInput in) throws IOException { in.readBoolean(), in.readImmutableMap(i -> i.readNamedWriteable(Expression.class)), readTimeSeriesFieldType(in), - // FIXME(gal, NOCOMMIT) Does this need to be protected by a version check? - in.readBoolean() ? in.readNamedWriteable(Expression.class) : null + in.getTransportVersion().supports(UNMAPPED_FIELDS_LOAD) ? in.readOptionalNamedWriteable(Expression.class) : null ); } @@ -67,12 +74,7 @@ public void writeContent(StreamOutput out) throws IOException { out.writeBoolean(isAggregatable()); out.writeMap(getIndexToConversionExpressions(), (o, v) -> out.writeNamedWriteable(v)); writeTimeSeriesFieldType(out); - if (potentiallyUnmappedExpression == null) { - out.writeBoolean(false); - } else { - out.writeBoolean(true); - out.writeNamedWriteable(potentiallyUnmappedExpression); - } + out.writeOptionalNamedWriteable(out.getTransportVersion().supports(UNMAPPED_FIELDS_LOAD) ? potentiallyUnmappedExpression : null); } public String getWriteableName() { @@ -151,6 +153,6 @@ public int hashCode() { @Override public String toString() { - return super.toString() + " (" + indexToConversionExpressions + ")"; + return Strings.format("%s (%s, %)", super.toString(), indexToConversionExpressions, potentiallyUnmappedExpression); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java index 6f7ba9e27b68c..e987b69f5f202 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java @@ -528,7 +528,7 @@ record MergedResult(Map mapping, Map> field private static MergedResult mergeMappings(List mappingsPerIndex) { int numberOfIndices = mappingsPerIndex.size(); - Set allIndexNames = mappingsPerIndex.stream().map(MappingPerIndex::index).collect(Collectors.toSet()); + List allIndexNames = mappingsPerIndex.stream().map(MappingPerIndex::index).toList(); Map> columnNamesToFieldByIndices = new HashMap<>(); for (var mappingPerIndex : mappingsPerIndex) { for (var entry : mappingPerIndex.mapping().entrySet()) { @@ -540,12 +540,13 @@ private static MergedResult mergeMappings(List mappingsPerIndex Map> fieldToUnmappedIndices = new HashMap<>(); for (var e : columnNamesToFieldByIndices.entrySet()) { - if (e.getValue().size() < numberOfIndices) { - String fieldName = e.getKey(); - Set mappedIndices = e.getValue().keySet(); - Set unmappedIndices = new HashSet<>(allIndexNames); - unmappedIndices.removeAll(mappedIndices); - fieldToUnmappedIndices.put(fieldName, unmappedIndices); + Set mappedFields = e.getValue().keySet(); + if (mappedFields.size() < numberOfIndices) { + String columnName = e.getKey(); + Set unmappedIndices = allIndexNames.stream() + .filter(n -> mappedFields.contains(n) == false) + .collect(Collectors.toUnmodifiableSet()); + fieldToUnmappedIndices.put(columnName, unmappedIndices); } } var mappings = columnNamesToFieldByIndices.entrySet() From 5addb8ef2f85ca4f66dc4f8f36ceec52c8a097e1 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 23 Feb 2026 20:24:49 +0200 Subject: [PATCH 045/137] Fix unmapped field loading for type-conflicted fields When a field has both a type conflict (e.g. keyword vs text) and is unmapped in some indices, resolvePartiallyMapped was skipping it because it was already an InvalidMappedField. This prevented it from being upgraded to potentiallyUnmapped, so ResolveUnionTypes never set the potentiallyUnmappedExpression on the MultiTypeEsField, causing null values instead of loading from _source. Also fix source path resolution for unmapped fields in indices with dynamic:false and no mapped properties, where FieldTypeLookup.sourcePaths returns empty because fullNameToFieldType is empty. Co-authored-by: Cursor --- .../src/main/resources/unmapped-load.csv-spec | 14 +++++------ .../xpack/esql/analysis/Analyzer.java | 24 +++++++++---------- .../planner/EsPhysicalOperationProviders.java | 12 +++++++++- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index 8fffa7d85f923..b09dfc7efabbf 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -864,13 +864,13 @@ logs | 2023-10-23T13:55:01.546Z | More java stuff logs | 2023-10-23T13:55:01.545Z | Doing java stuff for 192.168.86.038 logs | 2023-10-23T13:55:01.544Z | Running cats (cycle 1) logs | 2023-10-23T13:55:01.543Z | Pinging 192.168.86.046 -no_mapping_sample_data | 2024-10-23T13:55:01.543Z | null -no_mapping_sample_data | 2024-10-23T13:53:55.832Z | null -no_mapping_sample_data | 2024-10-23T13:52:55.015Z | null -no_mapping_sample_data | 2024-10-23T13:51:54.732Z | null -no_mapping_sample_data | 2024-10-23T13:33:34.937Z | null -no_mapping_sample_data | 2024-10-23T12:27:28.948Z | null -no_mapping_sample_data | 2024-10-23T12:15:03.360Z | null +no_mapping_sample_data | 2024-10-23T13:55:01.543Z | Connected to 10.1.0.1! +no_mapping_sample_data | 2024-10-23T13:53:55.832Z | Connection error? +no_mapping_sample_data | 2024-10-23T13:52:55.015Z | Connection error? +no_mapping_sample_data | 2024-10-23T13:51:54.732Z | Connection error? +no_mapping_sample_data | 2024-10-23T13:33:34.937Z | 42 +no_mapping_sample_data | 2024-10-23T12:27:28.948Z | Connected to 10.1.0.2! +no_mapping_sample_data | 2024-10-23T12:15:03.360Z | Connected to 10.1.0.3! sample_data | 2023-10-23T13:55:01.543Z | Connected to 10.1.0.1 sample_data | 2023-10-23T13:53:55.832Z | Connection error sample_data | 2023-10-23T13:52:55.015Z | Connection error diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index 0768bb1d01412..eaf7bfd21178d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -1189,18 +1189,18 @@ private static LogicalPlan resolvePartiallyMapped(LogicalPlan plan, AnalyzerCont Map insistedMap = new HashMap<>(); var transformed = plan.transformExpressionsOnly(FieldAttribute.class, fa -> { var esField = fa.field(); - var isPotentiallyUnmapped = esField instanceof PotentiallyUnmappedKeywordEsField || esField instanceof InvalidMappedField; - if (isPotentiallyUnmapped == false) { - var existing = insistedMap.get(fa); - if (existing != null) { // field shows up multiple times in the node; return first processing - return existing; - } - // Field is partially unmapped. - if (indexResolutions.stream().anyMatch(r -> r.get().isPartiallyUnmappedField(fa.name()))) { - FieldAttribute newFA = fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa, indexResolutions); - insistedMap.put(fa, newFA); - return newFA; - } + if (esField instanceof PotentiallyUnmappedKeywordEsField + || (esField instanceof InvalidMappedField imf && imf.isPotentiallyUnmapped())) { + return fa; + } + var existing = insistedMap.get(fa); + if (existing != null) { // field shows up multiple times in the node; return first processing + return existing; + } + if (indexResolutions.stream().anyMatch(r -> r.get().isPartiallyUnmappedField(fa.name()))) { + FieldAttribute newFA = fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa, indexResolutions); + insistedMap.put(fa, newFA); + return newFA; } return fa; }); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java index c5498b8211979..a400162b0942e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java @@ -275,6 +275,12 @@ private static class DefaultShardContextForUnmappedField extends DefaultShardCon return superResult == null && name.equals(unmappedEsField.getName()) ? createUnmappedFieldType(name, this) : superResult; } + @Override + protected Set resolveSourcePaths(String name) { + var result = super.resolveSourcePaths(name); + return result.isEmpty() && name.equals(unmappedEsField.getName()) ? Set.of(name) : result; + } + static MappedFieldType createUnmappedFieldType(String name, DefaultShardContext context) { var builder = new KeywordFieldMapper.Builder(name, context.ctx.getIndexSettings()); builder.docValues(false); @@ -577,7 +583,7 @@ public SearchLookup lookup() { @Override public Set sourcePaths(String name) { - return ctx.sourcePath(name); + return resolveSourcePaths(name); } @Override @@ -618,6 +624,10 @@ public double storedFieldsSequentialProportion() { return EsqlPlugin.STORED_FIELDS_SEQUENTIAL_PROPORTION.get(ctx.getIndexSettings().getSettings()); } + protected Set resolveSourcePaths(String name) { + return ctx.sourcePath(name); + } + @Override public void close() { releasable.close(); From 256fb47bb8d5dcba4e6cc91d2b92007871049b4e Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 2 Feb 2026 21:52:36 +0200 Subject: [PATCH 046/137] ESQL: Add name IDs to golden tests; fix synthetic names --- .../xpack/esql/optimizer/GoldenTestCase.java | 60 ++++++++++++++++--- .../local_physical_optimization.expected | 26 ++++---- .../local_physical_optimization.expected | 26 ++++---- .../local_physical_optimization.expected | 26 ++++---- .../local_physical_optimization.expected | 18 +++--- .../local_physical_optimization.expected | 18 +++--- .../local_physical_optimization.expected | 18 +++--- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 12 ++-- .../local_physical_optimization.expected | 12 ++-- .../local_physical_optimization.expected | 12 ++-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 10 ++-- .../local_physical_optimization.expected | 10 ++-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 10 ++-- .../local_physical_optimization.expected | 10 ++-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 10 ++-- .../local_physical_optimization.expected | 10 ++-- .../local_physical_optimization.expected | 12 ++-- .../local_physical_optimization.expected | 12 ++-- .../local_physical_optimization.expected | 12 ++-- .../local_physical_optimization.expected | 14 ++--- .../local_physical_optimization.expected | 14 ++--- .../local_physical_optimization.expected | 36 +++++------ .../byte/local_physical_optimization.expected | 8 +-- .../date/local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../long/local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 8 +-- .../local_physical_optimization.expected | 26 ++++---- ...physical_optimization_data_driver.expected | 8 +-- .../local_reduce_planned_data_driver.expected | 8 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 ++-- .../physical_optimization.expected | 12 ++-- ...physical_optimization_data_driver.expected | 12 ++-- .../local_reduce_planned_data_driver.expected | 10 ++-- ...ocal_reduce_planned_reduce_driver.expected | 10 ++-- .../physical_optimization.expected | 14 ++--- ...physical_optimization_data_driver.expected | 12 ++-- .../local_reduce_planned_data_driver.expected | 10 ++-- ...ocal_reduce_planned_reduce_driver.expected | 10 ++-- .../physical_optimization.expected | 14 ++--- ...physical_optimization_data_driver.expected | 18 +++--- .../local_reduce_planned_data_driver.expected | 16 ++--- ...ocal_reduce_planned_reduce_driver.expected | 10 ++-- .../physical_optimization.expected | 18 +++--- ...physical_optimization_data_driver.expected | 8 +-- .../local_reduce_planned_data_driver.expected | 8 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 ++-- .../physical_optimization.expected | 12 ++-- ...physical_optimization_data_driver.expected | 8 +-- .../local_reduce_planned_data_driver.expected | 8 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 ++-- .../physical_optimization.expected | 14 ++--- ...physical_optimization_data_driver.expected | 14 ++--- ...ysical_optimization_reduce_driver.expected | 6 +- .../local_reduce_planned_data_driver.expected | 12 ++-- ...ocal_reduce_planned_reduce_driver.expected | 6 +- .../physical_optimization.expected | 14 ++--- ...physical_optimization_data_driver.expected | 8 +-- .../local_reduce_planned_data_driver.expected | 8 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 ++-- .../physical_optimization.expected | 12 ++-- ...physical_optimization_data_driver.expected | 8 +-- .../local_reduce_planned_data_driver.expected | 10 ++-- ...ocal_reduce_planned_reduce_driver.expected | 10 ++-- .../physical_optimization.expected | 14 ++--- ...physical_optimization_data_driver.expected | 8 +-- .../local_reduce_planned_data_driver.expected | 8 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 ++-- .../physical_optimization.expected | 16 ++--- ...physical_optimization_data_driver.expected | 8 +-- .../local_reduce_planned_data_driver.expected | 8 +-- ...ocal_reduce_planned_reduce_driver.expected | 10 ++-- .../physical_optimization.expected | 12 ++-- 87 files changed, 547 insertions(+), 501 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 4527c52bcfefa..8db76ff979eaa 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -58,7 +58,10 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.EnumSet; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -384,23 +387,66 @@ private static Test.TestResult createNewOutput(Path output, QueryPlan plan) t if (output.toString().contains("extra")) { throw new IllegalStateException("Extra output files should not be created automatically:" + output); } - Files.writeString(output, toString(plan), StandardCharsets.UTF_8); + Files.writeString(output, normalizeNameIds(plan), StandardCharsets.UTF_8); return Test.TestResult.CREATED; } - private static String toString(Node plan) { - String planString = plan.toString(Node.NodeStringFormat.FULL); - String withoutSyntheticPatterns = SYNTHETIC_PATTERN.matcher(planString).replaceAll("\\$\\$$1"); - return IDENTIFIER_PATTERN.matcher(withoutSyntheticPatterns).replaceAll(""); + /** + * Rewrites node IDs ({@code #n}) in the plan string to a stable numbering by order of first appearance. + * Actual IDs assi;ned during plan building can vary between runs, so this is needed to keep golden output deterministic. + */ + private static String normalizeNameIds(Node plan) { + String full = plan.toString(Node.NodeStringFormat.FULL); + String normalized = normalizeSyntheticNames(full); + Matcher matcher = IDENTIFIER_PATTERN.matcher(normalized); + StringBuilder sb = new StringBuilder(); + int lastEnd = 0; + var idMap = new IdMap(); + while (matcher.find()) { + sb.append(normalized, lastEnd, matcher.start()); + int originalId = Integer.parseInt(matcher.group().substring(1)); // Drop the initial '#' prefix + sb.append("#").append(idMap.getId(originalId)); + lastEnd = matcher.end(); + } + sb.append(normalized, lastEnd, normalized.length()); + return sb.toString(); + } + + /** + * Normalizes synthetic attribute names of the form $$something($something)* that are followed by # (node id). + * Replaces them with $$firstSegment$runningInt so golden output is stable across runs. + */ + private static String normalizeSyntheticNames(String full) { + Matcher matcher = SYNTHETIC_PATTERN.matcher(full); + StringBuilder sb = new StringBuilder(); + int lastEnd = 0; + var idMap = new IdMap(); + while (matcher.find()) { + sb.append(full, lastEnd, matcher.start()); + String firstSegment = matcher.group(1); + sb.append("$$").append(firstSegment).append("$").append(idMap.getId(firstSegment)); + lastEnd = matcher.end(); + } + sb.append(full, lastEnd, full.length()); + return sb.toString(); } // Matches synthetic names like $$alias$1$2#3, since those $digits are generated during the test run and may differ each time. The // #digit are removed by the next pattern. - private static final Pattern SYNTHETIC_PATTERN = Pattern.compile("\\$\\$([^$\\s]+)(\\$\\d+)*(?=[{#])"); + private static final Pattern SYNTHETIC_PATTERN = Pattern.compile("\\$\\$([^$\\s]+)(\\$\\d+)+(?=[{#])"); private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("#\\d+"); + private static class IdMap { + private final Map map = new HashMap<>(); + private int counter = 0; + + public int getId(K key) { + return map.computeIfAbsent(key, k -> counter++); + } + } + private static Test.TestResult verifyExisting(Path output, QueryPlan plan) throws IOException { - String testString = normalize(toString(plan)); + String testString = normalize(normalizeNameIds(plan)); if (testString.equals(normalize(Files.readString(output)))) { if (System.getProperty("golden.cleanactual") != null) { Path path = actualPath(output); diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected index 961fe3106b9dd..504e54c3064ee 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected @@ -1,13 +1,13 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],SINGLE,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_EvalExec[[BUCKET(date{r},P1D[DATE_PERIOD]) AS x]] - \_MergeExec[[date{r}]] - |_ProjectExec[[date{f}]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],SINGLE,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_EvalExec[[BUCKET(date{r}#4,P1D[DATE_PERIOD]) AS x#0]] + \_MergeExec[[date{r}#4]] + |_ProjectExec[[date{f}#5]] | \_LimitExec[1000[INTEGER],null] - | \_ExchangeExec[[date{f}],false] - | \_ProjectExec[[date{f}]] - | \_FieldExtractExec[date{f}]<[],[]> - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ + | \_ExchangeExec[[date{f}#5],false] + | \_ProjectExec[[date{f}#5]] + | \_FieldExtractExec[date{f}#5]<[],[]> + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#6], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "integer", "next" : { @@ -21,12 +21,12 @@ LimitExec[1000[INTEGER],null] "source" : "integer > 100@2:15" } }, tags=[]]]] - \_ProjectExec[[date{f}]] + \_ProjectExec[[date{f}#7]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[date{f}],false] - \_ProjectExec[[date{f}]] - \_FieldExtractExec[date{f}]<[],[]> - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ + \_ExchangeExec[[date{f}#7],false] + \_ProjectExec[[date{f}#7]] + \_FieldExtractExec[date{f}#7]<[],[]> + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "match" : { "keyword" : { "query" : "keyword", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected index 427b439ba70cb..72dbdcc974f68 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected @@ -1,13 +1,13 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],SINGLE,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_EvalExec[[DATETRUNC(P1D[DATE_PERIOD],date{r}) AS x]] - \_MergeExec[[date{r}]] - |_ProjectExec[[date{f}]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],SINGLE,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_EvalExec[[DATETRUNC(P1D[DATE_PERIOD],date{r}#4) AS x#0]] + \_MergeExec[[date{r}#4]] + |_ProjectExec[[date{f}#5]] | \_LimitExec[1000[INTEGER],null] - | \_ExchangeExec[[date{f}],false] - | \_ProjectExec[[date{f}]] - | \_FieldExtractExec[date{f}]<[],[]> - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ + | \_ExchangeExec[[date{f}#5],false] + | \_ProjectExec[[date{f}#5]] + | \_FieldExtractExec[date{f}#5]<[],[]> + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#6], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "integer", "next" : { @@ -21,12 +21,12 @@ LimitExec[1000[INTEGER],null] "source" : "integer > 100@2:15" } }, tags=[]]]] - \_ProjectExec[[date{f}]] + \_ProjectExec[[date{f}#7]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[date{f}],false] - \_ProjectExec[[date{f}]] - \_FieldExtractExec[date{f}]<[],[]> - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ + \_ExchangeExec[[date{f}#7],false] + \_ProjectExec[[date{f}#7]] + \_FieldExtractExec[date{f}#7]<[],[]> + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "match" : { "keyword" : { "query" : "keyword", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected index 668bab853e771..5c5cb8da952c2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected @@ -1,13 +1,13 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],SINGLE,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_EvalExec[[ROUNDTO(date{r},1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x]] - \_MergeExec[[date{r}]] - |_ProjectExec[[date{f}]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],SINGLE,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_EvalExec[[ROUNDTO(date{r}#4,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] + \_MergeExec[[date{r}#4]] + |_ProjectExec[[date{f}#5]] | \_LimitExec[1000[INTEGER],null] - | \_ExchangeExec[[date{f}],false] - | \_ProjectExec[[date{f}]] - | \_FieldExtractExec[date{f}]<[],[]> - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ + | \_ExchangeExec[[date{f}#5],false] + | \_ProjectExec[[date{f}#5]] + | \_FieldExtractExec[date{f}#5]<[],[]> + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#6], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "integer", "next" : { @@ -21,12 +21,12 @@ LimitExec[1000[INTEGER],null] "source" : "integer > 100@2:15" } }, tags=[]]]] - \_ProjectExec[[date{f}]] + \_ProjectExec[[date{f}#7]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[date{f}],false] - \_ProjectExec[[date{f}]] - \_FieldExtractExec[date{f}]<[],[]> - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ + \_ExchangeExec[[date{f}#7],false] + \_ProjectExec[[date{f}#7]] + \_FieldExtractExec[date{f}#7]<[],[]> + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "match" : { "keyword" : { "query" : "keyword", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected index 474d85c27e113..37d5c04ccc89b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected @@ -1,11 +1,11 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[ROUNDTO(date{f},1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x]] - \_FieldExtractExec[date{f}]<[],[]> - \_LookupJoinExec[[integer{f}],[language_code{f}],[],null] - |_FieldExtractExec[integer{f}]<[],[]> - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[ROUNDTO(date{f}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] + \_FieldExtractExec[date{f}#6]<[],[]> + \_LookupJoinExec[[integer{f}#7],[language_code{f}#8],[],null] + |_FieldExtractExec[integer{f}#7]<[],[]> + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#9], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -EsRelation[languages_lookup][LOOKUP][language_code{f}]<>]] \ No newline at end of file +EsRelation[languages_lookup][LOOKUP][language_code{f}#8]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected index 474d85c27e113..37d5c04ccc89b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected @@ -1,11 +1,11 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[ROUNDTO(date{f},1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x]] - \_FieldExtractExec[date{f}]<[],[]> - \_LookupJoinExec[[integer{f}],[language_code{f}],[],null] - |_FieldExtractExec[integer{f}]<[],[]> - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[ROUNDTO(date{f}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] + \_FieldExtractExec[date{f}#6]<[],[]> + \_LookupJoinExec[[integer{f}#7],[language_code{f}#8],[],null] + |_FieldExtractExec[integer{f}#7]<[],[]> + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#9], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -EsRelation[languages_lookup][LOOKUP][language_code{f}]<>]] \ No newline at end of file +EsRelation[languages_lookup][LOOKUP][language_code{f}#8]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected index 474d85c27e113..37d5c04ccc89b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected @@ -1,11 +1,11 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[ROUNDTO(date{f},1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x]] - \_FieldExtractExec[date{f}]<[],[]> - \_LookupJoinExec[[integer{f}],[language_code{f}],[],null] - |_FieldExtractExec[integer{f}]<[],[]> - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[ROUNDTO(date{f}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] + \_FieldExtractExec[date{f}#6]<[],[]> + \_LookupJoinExec[[integer{f}#7],[language_code{f}#8],[],null] + |_FieldExtractExec[integer{f}#7]<[],[]> + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#9], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -EsRelation[languages_lookup][LOOKUP][language_code{f}]<>]] \ No newline at end of file +EsRelation[languages_lookup][LOOKUP][language_code{f}#8]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/local_physical_optimization.expected index ef1ef15736930..452b37138c025 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/local_physical_optimization.expected index f5a5c391169bb..b1eba3348e69d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/round_to/local_physical_optimization.expected index cf999b9b04435..ee48e2b81fe3e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/round_to/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/local_physical_optimization.expected index ef1ef15736930..452b37138c025 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/local_physical_optimization.expected index f5a5c391169bb..b1eba3348e69d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/round_to/local_physical_optimization.expected index cf999b9b04435..ee48e2b81fe3e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/round_to/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected index 63a896f2a8f23..9bed443f7dbca 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected @@ -1,10 +1,10 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[SUM(long{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long), COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[SUM(long{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long), COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],24] - \_FieldExtractExec[long{f}]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] + \_ExchangeExec[[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],true] + \_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] + \_FieldExtractExec[long{f}#1]<[],[]> + \_EvalExec[[$$date$round_to$datetime{f}#12 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#13, $$date$round_to$datetime{f}#12], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected index 0605eac068d20..8a37befcc7c7e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected @@ -1,10 +1,10 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[SUM(long{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long), COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[SUM(long{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long), COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],24] - \_FieldExtractExec[long{f}]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] + \_ExchangeExec[[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],true] + \_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] + \_FieldExtractExec[long{f}#1]<[],[]> + \_EvalExec[[$$date$round_to$datetime{f}#12 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#13, $$date$round_to$datetime{f}#12], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected index 6b66c077f925b..dd6350bd70a36 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected @@ -1,10 +1,10 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[SUM(long{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long), COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[SUM(long{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long), COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$sum(long)$sum{r}, $$sum(long)$seen{r}, $$count(*)$count{r}, $$count(*)$seen{r}],24] - \_FieldExtractExec[long{f}]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] + \_ExchangeExec[[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],true] + \_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] + \_FieldExtractExec[long{f}#1]<[],[]> + \_EvalExec[[$$date$round_to$datetime{f}#12 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#13, $$date$round_to$datetime{f}#12], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/local_physical_optimization.expected index dc56c28f87e93..6af84798b0c5b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "range" : { "date" : { @@ -42,4 +42,4 @@ LimitExec[1000[INTEGER],null] "boost" : 0.0 } } -}, tags=[1698019200000]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[1698019200000]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected index 395483c2bb606..8b039c4db5c27 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected index fa6cea028e09c..1783e8bca9fb9 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/local_physical_optimization.expected index dc56c28f87e93..6af84798b0c5b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "range" : { "date" : { @@ -42,4 +42,4 @@ LimitExec[1000[INTEGER],null] "boost" : 0.0 } } -}, tags=[1698019200000]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[1698019200000]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected index b2f7f6047fbc3..741c5cc853d00 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected index 479e0224b6622..ba745f8603cf2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/local_physical_optimization.expected index dc56c28f87e93..6af84798b0c5b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "range" : { "date" : { @@ -42,4 +42,4 @@ LimitExec[1000[INTEGER],null] "boost" : 0.0 } } -}, tags=[1698019200000]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[1698019200000]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected index 23b908e99a46f..3bb91af178169 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected index 186576dc41e63..0adf9b4716949 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],INITIAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],16] - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] + \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected index ccee8d2c5df22..54ec4005471fb 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected @@ -1,10 +1,10 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],long{f} > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10, x{r}],FINAL,[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],long{f} > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10, x{r}],INITIAL,[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],16] - \_FieldExtractExec[long{f}]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],FINAL,[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],null] + \_ExchangeExec[[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],INITIAL,[x{r}#0, $$count(*) where long > 10$count{r}#5, $$count(*) where long > 10$seen{r}#6],16] + \_FieldExtractExec[long{f}#1]<[],[]> + \_EvalExec[[$$date$round_to$datetime{f}#7 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8, $$date$round_to$datetime{f}#7], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected index 8fcf95e865e7b..8665d69bc4af1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected @@ -1,10 +1,10 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],long{f} > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10, x{r}],FINAL,[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],long{f} > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10, x{r}],INITIAL,[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],16] - \_FieldExtractExec[long{f}]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],FINAL,[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],null] + \_ExchangeExec[[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],INITIAL,[x{r}#0, $$count(*) where long > 10$count{r}#5, $$count(*) where long > 10$seen{r}#6],16] + \_FieldExtractExec[long{f}#1]<[],[]> + \_EvalExec[[$$date$round_to$datetime{f}#7 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8, $$date$round_to$datetime{f}#7], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected index 01cb9eab075bb..d59fd1a30f5dc 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected @@ -1,10 +1,10 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],long{f} > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10, x{r}],FINAL,[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],true] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],long{f} > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10, x{r}],INITIAL,[x{r}, $$count(*) where long > 10$count{r}, $$count(*) where long > 10$seen{r}],16] - \_FieldExtractExec[long{f}]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f} AS x]] - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],FINAL,[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],null] + \_ExchangeExec[[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],true] + \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],INITIAL,[x{r}#0, $$count(*) where long > 10$count{r}#5, $$count(*) where long > 10$seen{r}#6],16] + \_FieldExtractExec[long{f}#1]<[],[]> + \_EvalExec[[$$date$round_to$datetime{f}#7 AS x#0]] + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8, $$date$round_to$datetime{f}#7], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected index 046b0b2603e13..f4aec5a235e42 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[!alias_integer, date{f}, x{r}]] -\_TopNExec[[Order[date{f},ASC,LAST]],5[INTEGER],null] - \_ExchangeExec[[!alias_integer, date{f}, x{r}],false] - \_ProjectExec[[!alias_integer, date{f}, x{r}]] +ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] +\_TopNExec[[Order[date{f}#0,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[!alias_integer, date{f}#0, x{r}#1],false] + \_ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] \_FieldExtractExec[!alias_integer]<[],[]> - \_EvalExec[[ROUNDTO(date{f},1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x]] - \_FieldExtractExec[date{f}]<[],[]> - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[5], sort[[FieldSort[field=date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[1056] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file + \_EvalExec[[ROUNDTO(date{f}#0,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#1]] + \_FieldExtractExec[date{f}#0]<[],[]> + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#2], limit[5], sort[[FieldSort[field=date{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[1056] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected index 046b0b2603e13..f4aec5a235e42 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[!alias_integer, date{f}, x{r}]] -\_TopNExec[[Order[date{f},ASC,LAST]],5[INTEGER],null] - \_ExchangeExec[[!alias_integer, date{f}, x{r}],false] - \_ProjectExec[[!alias_integer, date{f}, x{r}]] +ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] +\_TopNExec[[Order[date{f}#0,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[!alias_integer, date{f}#0, x{r}#1],false] + \_ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] \_FieldExtractExec[!alias_integer]<[],[]> - \_EvalExec[[ROUNDTO(date{f},1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x]] - \_FieldExtractExec[date{f}]<[],[]> - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[5], sort[[FieldSort[field=date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[1056] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file + \_EvalExec[[ROUNDTO(date{f}#0,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#1]] + \_FieldExtractExec[date{f}#0]<[],[]> + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#2], limit[5], sort[[FieldSort[field=date{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[1056] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected index 689d91b4b0781..d6af15a5d5b6f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected @@ -1,14 +1,14 @@ LimitExec[1000[INTEGER],null] -\_MergeExec[[x{r}, y{r}, hd{r}, _fork{r}]] - |_ProjectExec[[x{r}, y{r}, hd{r}, _fork{r}]] - | \_EvalExec[[fork1[KEYWORD] AS _fork]] +\_MergeExec[[x{r}#0, y{r}#1, hd{r}#2, _fork{r}#3]] + |_ProjectExec[[x{r}#4, y{r}#5, hd{r}#6, _fork{r}#7]] + | \_EvalExec[[fork1[KEYWORD] AS _fork#7]] | \_LimitExec[1000[INTEGER],null] - | \_AggregateExec[[hd{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x, MAX(long{f},true[BOOLEAN],PT0S[TIME_DURATION]) AS y, hd{r}],FINAL,[hd{r}, $$x$count{r}, $$x$seen{r}, $$y$max{r}, $$y$seen{r}],null] - | \_ExchangeExec[[hd{r}, $$x$count{r}, $$x$seen{r}, $$y$max{r}, $$y$seen{r}],true] - | \_AggregateExec[[hd{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x, MAX(long{f},true[BOOLEAN],PT0S[TIME_DURATION]) AS y, hd{r}],INITIAL,[hd{r}, $$x$count{r}, $$x$seen{r}, $$y$max{r}, $$y$seen{r}],24] - | \_FieldExtractExec[long{f}]<[],[]> - | \_EvalExec[[$$date$round_to$datetime{f} AS hd]] - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}, $$date$round_to$datetime{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ + | \_AggregateExec[[hd{r}#6],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#4, MAX(long{f}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#5, hd{r}#6],FINAL,[hd{r}#6, $$x$count{r}#9, $$x$seen{r}#10, $$y$max{r}#11, $$y$seen{r}#12],null] + | \_ExchangeExec[[hd{r}#6, $$x$count{r}#9, $$x$seen{r}#10, $$y$max{r}#11, $$y$seen{r}#12],true] + | \_AggregateExec[[hd{r}#6],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#4, MAX(long{f}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#5, hd{r}#6],INITIAL,[hd{r}#6, $$x$count{r}#13, $$x$seen{r}#14, $$y$max{r}#15, $$y$seen{r}#16],24] + | \_FieldExtractExec[long{f}#8]<[],[]> + | \_EvalExec[[$$date$round_to$datetime{f}#17 AS hd#6]] + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#18, $$date$round_to$datetime{f}#17], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", "next" : { @@ -83,13 +83,13 @@ LimitExec[1000[INTEGER],null] "boost" : 1.0 } }, tags=[null]]]] - \_ProjectExec[[x{r}, y{r}, hd{r}, _fork{r}]] - \_EvalExec[[fork2[KEYWORD] AS _fork]] + \_ProjectExec[[x{r}#19, y{r}#20, hd{r}#21, _fork{r}#7]] + \_EvalExec[[fork2[KEYWORD] AS _fork#7]] \_LimitExec[1000[INTEGER],null] - \_AggregateExec[[hd{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x, MIN(long{f},true[BOOLEAN],PT0S[TIME_DURATION]) AS y, hd{r}],FINAL,[hd{r}, $$x$count{r}, $$x$seen{r}, $$y$min{r}, $$y$seen{r}],null] - \_ExchangeExec[[hd{r}, $$x$count{r}, $$x$seen{r}, $$y$min{r}, $$y$seen{r}],true] - \_AggregateExec[[hd{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x, MIN(long{f},true[BOOLEAN],PT0S[TIME_DURATION]) AS y, hd{r}],INITIAL,[hd{r}, $$x$count{r}, $$x$seen{r}, $$y$min{r}, $$y$seen{r}],24] - \_FieldExtractExec[long{f}]<[],[]> - \_EvalExec[[DATETRUNC(P2D[DATE_PERIOD],date{f}) AS hd]] - \_FieldExtractExec[date{f}]<[],[]> - \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file + \_AggregateExec[[hd{r}#21],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#19, MIN(long{f}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#20, hd{r}#21],FINAL,[hd{r}#21, $$x$count{r}#23, $$x$seen{r}#24, $$y$min{r}#25, $$y$seen{r}#26],null] + \_ExchangeExec[[hd{r}#21, $$x$count{r}#23, $$x$seen{r}#24, $$y$min{r}#25, $$y$seen{r}#26],true] + \_AggregateExec[[hd{r}#21],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#19, MIN(long{f}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#20, hd{r}#21],INITIAL,[hd{r}#21, $$x$count{r}#27, $$x$seen{r}#28, $$y$min{r}#29, $$y$seen{r}#30],24] + \_FieldExtractExec[long{f}#22]<[],[]> + \_EvalExec[[DATETRUNC(P2D[DATE_PERIOD],date{f}#31) AS hd#21]] + \_FieldExtractExec[date{f}#31]<[],[]> + \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#32], limit[], sort[] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/local_physical_optimization.expected index 23bb5e9c22897..5315aaeb6b782 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "byte", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/local_physical_optimization.expected index 50845a7e8de0e..a917d136623a5 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/local_physical_optimization.expected index 082cecd12d88a..66b986835d508 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date_nanos", @@ -76,4 +76,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/local_physical_optimization.expected index 88f9a412070ba..d7f1b8f132836 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "double", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/local_physical_optimization.expected index 66daa7da9316f..299660977cb4e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "float", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/local_physical_optimization.expected index f4b5190ff7395..7f6523fa91e37 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "half_float", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/local_physical_optimization.expected index fba0ce864cf57..bd20ccd161980 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "integer", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/long/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/long/local_physical_optimization.expected index 45671a3481eff..cf3a620024a4e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/long/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/long/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "long", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/local_physical_optimization.expected index d2a0558821e41..c980fac8998ca 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "scaled_float", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/local_physical_optimization.expected index dda69d55339db..ad219641bde8c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/local_physical_optimization.expected @@ -1,7 +1,7 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*), x{r}],FINAL,[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],null] - \_ExchangeExec[[x{r}, $$count(*)$count{r}, $$count(*)$seen{r}],true] - \_FilterExec[$$count(*)$count{r} > 0[LONG]] +\_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] + \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] + \_FilterExec[$$count(*)$count{r}#4 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "short", @@ -68,4 +68,4 @@ LimitExec[1000[INTEGER],null] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$count(*)$count{r}, $$count(*)$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected index 7dc015da213c7..9f3fe63e4a21f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected @@ -1,16 +1,16 @@ -ProjectExec[[x{r}, cnt{r}, date{r}]] +ProjectExec[[x{r}#0, cnt{r}#1, date{r}#2]] \_LimitExec[1000[INTEGER],null] - \_MergeExec[[alias_integer{r}, boolean{r}, byte{r}, constant_keyword-foo{r}, date{r}, date_nanos{r}, dense_vector{r}, double{r}, float{r}, half_float{r}, integer{r}, ip{r}, keyword{r}, long{r}, scaled_float{r}, semantic_text{r}, short{r}, text{r}, unsigned_long{r}, version{r}, wildcard{r}, cnt{r}, x{r}]] - |_ExchangeExec[[alias_integer{r}, boolean{f}, byte{f}, constant_keyword-foo{f}, date{f}, date_nanos{f}, dense_vector{f}, double{f}, float{f}, half_float{f}, integer{f}, ip{f}, keyword{f}, long{f}, scaled_float{f}, semantic_text{f}, short{f}, text{f}, unsigned_long{f}, version{f}, wildcard{f}, cnt{r}, x{r}],false] - | \_ProjectExec[[alias_integer{r}, boolean{f}, byte{f}, constant_keyword-foo{f}, date{f}, date_nanos{f}, dense_vector{f}, double{f}, float{f}, half_float{f}, integer{f}, ip{f}, keyword{f}, long{f}, scaled_float{f}, semantic_text{f}, short{f}, text{f}, unsigned_long{f}, version{f}, wildcard{f}, cnt{r}, x{r}]] - | \_FieldExtractExec[boolean{f}, byte{f}, constant_keyword-foo{f}, date{f}, date_nanos{f}, dense_vector{f}, double{f}, float{f}, half_float{f}, integer{f}, ip{f}, keyword{f}, long{f}, scaled_float{f}, semantic_text{f}, short{f}, text{f}, unsigned_long{f}, version{f}, wildcard{f}]<[],[]> - | \_EvalExec[[null[LONG] AS cnt, null[DATETIME] AS x, null[KEYWORD] AS alias_integer]] - | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[6472] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] - \_ProjectExec[[alias_integer{r}, boolean{r}, byte{r}, constant_keyword-foo{r}, date{r}, date_nanos{r}, dense_vector{r}, double{r}, float{r}, half_float{r}, integer{r}, ip{r}, keyword{r}, long{r}, scaled_float{r}, semantic_text{r}, short{r}, text{r}, unsigned_long{r}, version{r}, wildcard{r}, cnt{r}, x{r}]] - \_EvalExec[[null[KEYWORD] AS alias_integer, null[BOOLEAN] AS boolean, null[INTEGER] AS byte, null[KEYWORD] AS constant_keyword-foo, null[DATETIME] AS date, null[DATE_NANOS] AS date_nanos, null[DENSE_VECTOR] AS dense_vector, null[DOUBLE] AS double, null[DOUBLE] AS float, null[DOUBLE] AS half_float, null[INTEGER] AS integer, null[IP] AS ip, null[KEYWORD] AS keyword, null[LONG] AS long, null[DOUBLE] AS scaled_float, null[TEXT] AS semantic_text, null[INTEGER] AS short, null[TEXT] AS text, null[UNSIGNED_LONG] AS unsigned_long, null[VERSION] AS version, null[KEYWORD] AS wildcard, null[KEYWORD] AS alias_integer]] - \_AggregateExec[[x{r}],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt, x{r}],FINAL,[x{r}, $$cnt$count{r}, $$cnt$seen{r}],null] - \_ExchangeExec[[x{r}, $$cnt$count{r}, $$cnt$seen{r}],true] - \_FilterExec[$$cnt$count{r} > 0[LONG]] + \_MergeExec[[alias_integer{r}#3, boolean{r}#4, byte{r}#5, constant_keyword-foo{r}#6, date{r}#2, date_nanos{r}#7, dense_vector{r}#8, double{r}#9, float{r}#10, half_float{r}#11, integer{r}#12, ip{r}#13, keyword{r}#14, long{r}#15, scaled_float{r}#16, semantic_text{r}#17, short{r}#18, text{r}#19, unsigned_long{r}#20, version{r}#21, wildcard{r}#22, cnt{r}#1, x{r}#0]] + |_ExchangeExec[[alias_integer{r}#23, boolean{f}#24, byte{f}#25, constant_keyword-foo{f}#26, date{f}#27, date_nanos{f}#28, dense_vector{f}#29, double{f}#30, float{f}#31, half_float{f}#32, integer{f}#33, ip{f}#34, keyword{f}#35, long{f}#36, scaled_float{f}#37, semantic_text{f}#38, short{f}#39, text{f}#40, unsigned_long{f}#41, version{f}#42, wildcard{f}#43, cnt{r}#44, x{r}#45],false] + | \_ProjectExec[[alias_integer{r}#23, boolean{f}#24, byte{f}#25, constant_keyword-foo{f}#26, date{f}#27, date_nanos{f}#28, dense_vector{f}#29, double{f}#30, float{f}#31, half_float{f}#32, integer{f}#33, ip{f}#34, keyword{f}#35, long{f}#36, scaled_float{f}#37, semantic_text{f}#38, short{f}#39, text{f}#40, unsigned_long{f}#41, version{f}#42, wildcard{f}#43, cnt{r}#44, x{r}#45]] + | \_FieldExtractExec[boolean{f}#24, byte{f}#25, constant_keyword-foo{f}#26, date{f}#27, date_nanos{f}#28, dense_vector{f}#29, double{f}#30, float{f}#31, half_float{f}#32, integer{f}#33, ip{f}#34, keyword{f}#35, long{f}#36, scaled_float{f}#37, semantic_text{f}#38, short{f}#39, text{f}#40, unsigned_long{f}#41, version{f}#42, wildcard{f}#43]<[],[]> + | \_EvalExec[[null[LONG] AS cnt#44, null[DATETIME] AS x#45, null[KEYWORD] AS alias_integer#23]] + | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#46], limit[], sort[] estimatedRowSize[6472] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] + \_ProjectExec[[alias_integer{r}#47, boolean{r}#48, byte{r}#49, constant_keyword-foo{r}#50, date{r}#51, date_nanos{r}#52, dense_vector{r}#53, double{r}#54, float{r}#55, half_float{r}#56, integer{r}#57, ip{r}#58, keyword{r}#59, long{r}#60, scaled_float{r}#61, semantic_text{r}#62, short{r}#63, text{r}#64, unsigned_long{r}#65, version{r}#66, wildcard{r}#67, cnt{r}#68, x{r}#69]] + \_EvalExec[[null[KEYWORD] AS alias_integer#70, null[BOOLEAN] AS boolean#48, null[INTEGER] AS byte#49, null[KEYWORD] AS constant_keyword-foo#50, null[DATETIME] AS date#51, null[DATE_NANOS] AS date_nanos#52, null[DENSE_VECTOR] AS dense_vector#53, null[DOUBLE] AS double#54, null[DOUBLE] AS float#55, null[DOUBLE] AS half_float#56, null[INTEGER] AS integer#57, null[IP] AS ip#58, null[KEYWORD] AS keyword#59, null[LONG] AS long#60, null[DOUBLE] AS scaled_float#61, null[TEXT] AS semantic_text#62, null[INTEGER] AS short#63, null[TEXT] AS text#64, null[UNSIGNED_LONG] AS unsigned_long#65, null[VERSION] AS version#66, null[KEYWORD] AS wildcard#67, null[KEYWORD] AS alias_integer#47]] + \_AggregateExec[[x{r}#69],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt#68, x{r}#69],FINAL,[x{r}#69, $$cnt$count{r}#71, $$cnt$seen{r}#72],null] + \_ExchangeExec[[x{r}#69, $$cnt$count{r}#71, $$cnt$seen{r}#72],true] + \_FilterExec[$$cnt$count{r}#73 > 0[LONG]] \_EsStatsQueryExec[all_types], statsByStat{queryBuilderAndTags=[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -85,4 +85,4 @@ ProjectExec[[x{r}, cnt{r}, date{r}]] ], "boost" : 1.0 } -}, tags=[null]]]}], query[][x{r}, $$cnt$count{r}, $$cnt$seen{r}], limit[], \ No newline at end of file +}, tags=[null]]]}], query[][x{r}#69, $$cnt$count{r}#73, $$cnt$seen{r}#74], limit[], \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected index 723ce904e88d3..fb387032f3d2a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[_doc{f}, hire_date{f}],false] -\_ProjectExec[[_doc{f}, hire_date{f}]] - \_FieldExtractExec[hire_date{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] +\_ProjectExec[[_doc{f}#0, hire_date{f}#1]] + \_FieldExtractExec[hire_date{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected index 391e45f5b0835..9db0da8910f5b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}, hire_date{f}],false] +ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, hire_date{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#0, hire_date{f}#1]] +\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#1, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected index 378271a5e3f37..4b4fc0c891ac1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] - \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> + \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected index cd76be3897e14..84b502cae4e25 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[hire_date{f}, salary{f}, emp_no{f}]] -\_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}, hire_date{f}, salary{f}],false] +ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] +\_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, hire_date{f}, salary{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] +\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected index 9bd1091990166..0315e1603645a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[_doc{f}, $$order_by{r}],false] -\_ProjectExec[[_doc{f}, $$order_by{r}]] - \_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],36] - \_EvalExec[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] - \_FieldExtractExec[height{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[_doc{f}#0, $$order_by$0{r}#1],false] +\_ProjectExec[[_doc{f}#0, $$order_by$0{r}#1]] + \_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],36] + \_EvalExec[[SIN(height{f}#2) * 2[INTEGER] AS $$order_by$0#1]] + \_FieldExtractExec[height{f}#2]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected index edd351fd4feb2..42e09257b6138 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[_doc{f}, $$order_by{r}],false] +ExchangeSinkExec[[_doc{f}#0, $$order_by$0{r}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, $$order_by{r}]] -\_TopN[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#0, $$order_by$0{r}#1]] +\_TopN[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}#2) * 2[INTEGER] AS $$order_by$0#1]] + \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#2, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected index 6122b8f73ddfa..d2459818c5588 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[hire_date{f}, $$order_by{r}],false] -\_ProjectExec[[hire_date{f}, $$order_by{r}]] - \_FieldExtractExec[hire_date{f}]<[],[]> - \_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, $$order_by{r}],false] \ No newline at end of file +ExchangeSinkExec[[hire_date{f}#0, $$order_by$0{r}#1],false] +\_ProjectExec[[hire_date{f}#0, $$order_by$0{r}#1]] + \_FieldExtractExec[hire_date{f}#0]<[],[]> + \_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#2, $$order_by$0{r}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected index 379de6ff82e29..71abdab6b07fe 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}]] -\_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[hire_date{f}, $$order_by{r}],false] +ProjectExec[[hire_date{f}#0]] +\_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[hire_date{f}#0, $$order_by$0{r}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[hire_date{f}, $$order_by{r}]] -\_TopN[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[hire_date{f}#0, $$order_by$0{r}#1]] +\_TopN[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}#2) * 2[INTEGER] AS $$order_by$0#1]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#2, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected index 18dffd6ba00d3..f1a5151c994d2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[_doc{f}, height{f}, $$order_by{r}],false] -\_ProjectExec[[_doc{f}, height{f}, $$order_by{r}]] - \_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],36] - \_EvalExec[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] - \_FieldExtractExec[height{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[_doc{f}#0, height{f}#1, $$order_by$0{r}#2],false] +\_ProjectExec[[_doc{f}#0, height{f}#1, $$order_by$0{r}#2]] + \_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],36] + \_EvalExec[[SIN(height{f}#1) * 2[INTEGER] AS $$order_by$0#2]] + \_FieldExtractExec[height{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected index 450d2bf335b05..202cc12a29fe2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[_doc{f}, height{f}, $$order_by{r}],false] +ExchangeSinkExec[[_doc{f}#0, height{f}#1, $$order_by$0{r}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, height{f}, $$order_by{r}]] -\_TopN[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#0, height{f}#1, $$order_by$0{r}#2]] +\_TopN[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}#1) * 2[INTEGER] AS $$order_by$0#2]] + \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#1, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected index e19d24b8b2b9f..88c85960c5dd2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[height{f}, hire_date{f}, $$order_by{r}],false] -\_ProjectExec[[height{f}, hire_date{f}, $$order_by{r}]] - \_FieldExtractExec[hire_date{f}]<[],[]> - \_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],44] - \_ExchangeSourceExec[[_doc{f}, height{f}, $$order_by{r}],false] \ No newline at end of file +ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2],false] +\_ProjectExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2]] + \_FieldExtractExec[hire_date{f}#1]<[],[]> + \_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],44] + \_ExchangeSourceExec[[_doc{f}#3, height{f}#0, $$order_by$0{r}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected index dd1f613d8bedf..b3fbad771e03e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}, height{f}]] -\_TopNExec[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[height{f}, hire_date{f}, $$order_by{r}],false] +ProjectExec[[hire_date{f}#0, height{f}#1]] +\_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[height{f}#1, hire_date{f}#0, $$order_by$0{r}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[height{f}, hire_date{f}, $$order_by{r}]] -\_TopN[[Order[$$order_by{r},ASC,LAST]],20[INTEGER],false] - \_Eval[[SIN(height{f}) * 2[INTEGER] AS $$order_by]] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[height{f}#1, hire_date{f}#0, $$order_by$0{r}#2]] +\_TopN[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],false] + \_Eval[[SIN(height{f}#1) * 2[INTEGER] AS $$order_by$0#2]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#1, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected index 16144b0f1de0f..0b739f1210f4d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected @@ -1,11 +1,11 @@ -ExchangeSinkExec[[_doc{f}, emp_no{f}, languages{f}, language_code{r}, language_name{f}],false] -\_ProjectExec[[_doc{f}, emp_no{f}, languages{f}, language_code{r}, language_name{f}]] - \_TopNExec[[Order[emp_no{f},ASC,LAST]],20[INTEGER],82] - \_FieldExtractExec[emp_no{f}]<[],[]> - \_LookupJoinExec[[language_code{r}],[language_code{f}],[language_name{f}],null] - |_EvalExec[[languages{f} AS language_code]] - | \_FieldExtractExec[languages{f}]<[],[]> - | \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query={ +ExchangeSinkExec[[_doc{f}#0, emp_no{f}#1, languages{f}#2, language_code{r}#3, language_name{f}#4],false] +\_ProjectExec[[_doc{f}#0, emp_no{f}#1, languages{f}#2, language_code{r}#3, language_name{f}#4]] + \_TopNExec[[Order[emp_no{f}#1,ASC,LAST]],20[INTEGER],82] + \_FieldExtractExec[emp_no{f}#1]<[],[]> + \_LookupJoinExec[[language_code{r}#3],[language_code{f}#5],[language_name{f}#4],null] + |_EvalExec[[languages{f}#2 AS language_code#3]] + | \_FieldExtractExec[languages{f}#2]<[],[]> + | \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[], sort[] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "emp_no", "next" : { @@ -22,4 +22,4 @@ ExchangeSinkExec[[_doc{f}, emp_no{f}, languages{f}, language_code{r}, language_n } }, tags=[]]]] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -EsRelation[languages_lookup][LOOKUP][language_code{f}, language_name{f}]<>]] \ No newline at end of file +EsRelation[languages_lookup][LOOKUP][language_code{f}#5, language_name{f}#4]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected index d8621a842a5f3..8f1164f38c747 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected @@ -1,9 +1,9 @@ -ExchangeSinkExec[[_doc{f}, emp_no{f}, languages{f}, language_code{r}, language_name{f}],false] +ExchangeSinkExec[[_doc{f}#0, emp_no{f}#1, languages{f}#2, language_code{r}#3, language_name{f}#4],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, emp_no{f}, languages{f}, language_code{r}, language_name{f}]] -\_TopN[[Order[emp_no{f},ASC,LAST]],20[INTEGER],false] - \_Join[LEFT,[language_code{r}],[language_code{f}],null] - |_Eval[[languages{f} AS language_code]] - | \_Filter[emp_no{f} >= 10091[INTEGER] AND emp_no{f} < 10094[INTEGER]] - | \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}, language_name{f}]<>]] \ No newline at end of file +Project[[_doc{f}#0, emp_no{f}#1, languages{f}#2, language_code{r}#3, language_name{f}#4]] +\_TopN[[Order[emp_no{f}#1,ASC,LAST]],20[INTEGER],false] + \_Join[LEFT,[language_code{r}#3],[language_code{f}#5],null] + |_Eval[[languages{f}#2 AS language_code#3]] + | \_Filter[emp_no{f}#1 >= 10091[INTEGER] AND emp_no{f}#1 < 10094[INTEGER]] + | \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#1, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#2, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#5, language_name{f}#4]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected index 1c739d108e561..19c98b1780f37 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}],false] -\_ProjectExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}]] - \_FieldExtractExec[avg_worked_seconds{f}, birth_date{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<[],[]> - \_TopNExec[[Order[emp_no{f},ASC,LAST]],20[INTEGER],430] - \_ExchangeSourceExec[[_doc{f}, emp_no{f}, languages{f}, language_code{r}, language_name{f}],false] \ No newline at end of file +ExchangeSinkExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] +\_ProjectExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24]] + \_FieldExtractExec[avg_worked_seconds{f}#0, birth_date{f}#1, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<[],[]> + \_TopNExec[[Order[emp_no{f}#2,ASC,LAST]],20[INTEGER],430] + \_ExchangeSourceExec[[_doc{f}#25, emp_no{f}#2, languages{f}#12, language_code{r}#23, language_name{f}#24],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected index 6de9cdeb68a29..438c1c6d34382 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected @@ -1,10 +1,10 @@ -TopNExec[[Order[emp_no{f},ASC,LAST]],20[INTEGER],null] -\_ExchangeExec[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}],false] +TopNExec[[Order[emp_no{f}#0,ASC,LAST]],20[INTEGER],null] +\_ExchangeExec[[avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#0, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}, language_code{r}, language_name{f}]] -\_TopN[[Order[emp_no{f},ASC,LAST]],20[INTEGER],false] - \_Join[LEFT,[language_code{r}],[language_code{f}],null] - |_Eval[[languages{f} AS language_code]] - | \_Filter[emp_no{f} >= 10091[INTEGER] AND emp_no{f} < 10094[INTEGER]] - | \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}, language_name{f}]<>]] \ No newline at end of file +Project[[avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#0, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24]] +\_TopN[[Order[emp_no{f}#0,ASC,LAST]],20[INTEGER],false] + \_Join[LEFT,[language_code{r}#23],[language_code{f}#25],null] + |_Eval[[languages{f}#12 AS language_code#23]] + | \_Filter[emp_no{f}#0 >= 10091[INTEGER] AND emp_no{f}#0 < 10094[INTEGER]] + | \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#0, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#25, language_name{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected index 8d71c6318ff7d..1c5150bf358d7 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[_doc{f}, hire_date{f}, height{f}],false] -\_ProjectExec[[_doc{f}, hire_date{f}, height{f}]] - \_FieldExtractExec[hire_date{f}, height{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST], FieldSort[field=height{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[32] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1, height{f}#2],false] +\_ProjectExec[[_doc{f}#0, hire_date{f}#1, height{f}#2]] + \_FieldExtractExec[hire_date{f}#1, height{f}#2]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST], FieldSort[field=height{f}#2, direction=ASC, nulls=LAST]]] estimatedRowSize[32] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected index 5ecfdc0e91ea9..494a0526f6dd3 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}, hire_date{f}, height{f}],false] +ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1, height{f}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, hire_date{f}, height{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST], Order[height{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#0, hire_date{f}#1, height{f}#2]] +\_TopN[[Order[hire_date{f}#1,ASC,LAST], Order[height{f}#2,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#2, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#1, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected index b4903131e7355..ab96def3b448c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, height{f}, hire_date{f}],false] -\_ProjectExec[[emp_no{f}, height{f}, hire_date{f}]] - \_FieldExtractExec[emp_no{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST], Order[height{f},ASC,LAST]],20[INTEGER],40] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}, height{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2],false] +\_ProjectExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2]] + \_FieldExtractExec[emp_no{f}#0]<[],[]> + \_TopNExec[[Order[hire_date{f}#2,ASC,LAST], Order[height{f}#1,ASC,LAST]],20[INTEGER],40] + \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#2, height{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected index 01e434d142dbc..64df823ba0bbf 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[hire_date{f}, emp_no{f}, height{f}]] -\_TopNExec[[Order[hire_date{f},ASC,LAST], Order[height{f},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}, height{f}, hire_date{f}],false] +ProjectExec[[hire_date{f}#0, emp_no{f}#1, height{f}#2]] +\_TopNExec[[Order[hire_date{f}#0,ASC,LAST], Order[height{f}#2,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}#1, height{f}#2, hire_date{f}#0],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, height{f}, hire_date{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST], Order[height{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#1, height{f}#2, hire_date{f}#0]] +\_TopN[[Order[hire_date{f}#0,ASC,LAST], Order[height{f}#2,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#1, first_name{f}#5, gender{f}#6, height{f}#2, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#0, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected index 723ce904e88d3..fb387032f3d2a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[_doc{f}, hire_date{f}],false] -\_ProjectExec[[_doc{f}, hire_date{f}]] - \_FieldExtractExec[hire_date{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] +\_ProjectExec[[_doc{f}#0, hire_date{f}#1]] + \_FieldExtractExec[hire_date{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected index 391e45f5b0835..9db0da8910f5b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}, hire_date{f}],false] +ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, hire_date{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#0, hire_date{f}#1]] +\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#1, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected index 378271a5e3f37..4b4fc0c891ac1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] - \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> + \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected index f614767fd6b3e..92cf16635a7dc 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}, salary{f}, emp_no{f}]] -\_TopNExec[[Order[salary{f},ASC,LAST]],10[INTEGER],null] - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}, hire_date{f}, salary{f}],false] +ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] +\_TopNExec[[Order[salary{f}#1,ASC,LAST]],10[INTEGER],null] + \_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, hire_date{f}, salary{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] +\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected index 2f239d653927e..f0d827b7d0c99 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,7 +1,7 @@ -ExchangeSinkExec[[emp_no{f}, job_positions{r}, salary{f}],false] -\_ProjectExec[[emp_no{f}, job_positions{r}, salary{f}]] - \_TopNExec[[Order[salary{f},ASC,LAST]],20[INTEGER],58] - \_MvExpandExec[job_positions{f},job_positions{r}] - \_ProjectExec[[emp_no{f}, job_positions{f}, salary{f}]] - \_FieldExtractExec[emp_no{f}, job_positions{f}, salary{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[], sort[] estimatedRowSize[62] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2]] + \_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] + \_MvExpandExec[job_positions{f}#3,job_positions{r}#1] + \_ProjectExec[[emp_no{f}#0, job_positions{f}#3, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0, job_positions{f}#3, salary{f}#2]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#4], limit[], sort[] estimatedRowSize[62] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected index 0c801590c80b7..a9639e399dec8 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected @@ -1,3 +1,3 @@ -ExchangeSinkExec[[emp_no{f}, job_positions{r}, salary{f}],false] -\_TopNExec[[Order[salary{f},ASC,LAST]],20[INTEGER],58] - \_ExchangeSourceExec[[emp_no{f}, job_positions{r}, salary{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] +\_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] + \_ExchangeSourceExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected index 5a4be4cccf576..baf5e66932990 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected @@ -1,7 +1,7 @@ -ExchangeSinkExec[[emp_no{f}, job_positions{r}, salary{f}],false] +ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, job_positions{r}, salary{f}]] -\_TopN[[Order[salary{f},ASC,LAST]],20[INTEGER],false] - \_MvExpand[job_positions{f},job_positions{r}] - \_Project[[emp_no{f}, job_positions{f}, salary{f}]] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#0, job_positions{r}#1, salary{f}#2]] +\_TopN[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],false] + \_MvExpand[job_positions{f}#3,job_positions{r}#1] + \_Project[[emp_no{f}#0, job_positions{f}#3, salary{f}#2]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#3, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected index 0c801590c80b7..a9639e399dec8 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected @@ -1,3 +1,3 @@ -ExchangeSinkExec[[emp_no{f}, job_positions{r}, salary{f}],false] -\_TopNExec[[Order[salary{f},ASC,LAST]],20[INTEGER],58] - \_ExchangeSourceExec[[emp_no{f}, job_positions{r}, salary{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] +\_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] + \_ExchangeSourceExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected index d53c3f7c10b84..7bd205fddb3bd 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected @@ -1,8 +1,8 @@ -TopNExec[[Order[salary{f},ASC,LAST]],20[INTEGER],null] -\_ExchangeExec[[emp_no{f}, job_positions{r}, salary{f}],false] +TopNExec[[Order[salary{f}#0,ASC,LAST]],20[INTEGER],null] +\_ExchangeExec[[emp_no{f}#1, job_positions{r}#2, salary{f}#0],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, job_positions{r}, salary{f}]] -\_TopN[[Order[salary{f},ASC,LAST]],20[INTEGER],false] - \_MvExpand[job_positions{f},job_positions{r}] - \_Project[[emp_no{f}, job_positions{f}, salary{f}]] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#1, job_positions{r}#2, salary{f}#0]] +\_TopN[[Order[salary{f}#0,ASC,LAST]],20[INTEGER],false] + \_MvExpand[job_positions{f}#3,job_positions{r}#2] + \_Project[[emp_no{f}#1, job_positions{f}#3, salary{f}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#1, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#3, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#0, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected index b3b5c1a34e4bc..d345864f4bcb2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[_doc{f}, height{f}],false] -\_ProjectExec[[_doc{f}, height{f}]] - \_FieldExtractExec[height{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=height{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[_doc{f}#0, height{f}#1],false] +\_ProjectExec[[_doc{f}#0, height{f}#1]] + \_FieldExtractExec[height{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[20], sort[[FieldSort[field=height{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected index 99ac7bd279208..8abcf07553c66 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}, height{f}],false] +ExchangeSinkExec[[_doc{f}#0, height{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, height{f}]] -\_TopN[[Order[height{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#0, height{f}#1]] +\_TopN[[Order[height{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#1, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected index 787b72a5c8f72..3425364e715c1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, height{f}],false] -\_ProjectExec[[emp_no{f}, height{f}]] - \_FieldExtractExec[emp_no{f}]<[],[]> - \_TopNExec[[Order[height{f},ASC,LAST]],20[INTEGER],32] - \_ExchangeSourceExec[[_doc{f}, height{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, height{f}#1],false] +\_ProjectExec[[emp_no{f}#0, height{f}#1]] + \_FieldExtractExec[emp_no{f}#0]<[],[]> + \_TopNExec[[Order[height{f}#1,ASC,LAST]],20[INTEGER],32] + \_ExchangeSourceExec[[_doc{f}#2, height{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected index 896efe01a59ec..e659e9ce08d64 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[emp_no{f}, height{f}]] -\_TopNExec[[Order[height{f},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}, height{f}],false] +ProjectExec[[emp_no{f}#0, height{f}#1]] +\_TopNExec[[Order[height{f}#1,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}#0, height{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, height{f}]] -\_TopN[[Order[height{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#0, height{f}#1]] +\_TopN[[Order[height{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#0, first_name{f}#4, gender{f}#5, height{f}#1, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected index 81d5401085264..2022c5678fda7 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected @@ -1,7 +1,7 @@ -ExchangeSinkExec[[_doc{f}, salary{f}, hire_date{f}],false] -\_ProjectExec[[_doc{f}, salary{f}, hire_date{f}]] - \_FieldExtractExec[salary{f}, hire_date{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query={ +ExchangeSinkExec[[_doc{f}#0, salary{f}#1, hire_date{f}#2],false] +\_ProjectExec[[_doc{f}#0, salary{f}#1, hire_date{f}#2]] + \_FieldExtractExec[salary{f}#1, hire_date{f}#2]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[20], sort[[FieldSort[field=hire_date{f}#2, direction=ASC, nulls=LAST]]] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "salary", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected index 435ccfdcf08e0..a3bf3dbd30194 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[_doc{f}, salary{f}, hire_date{f}],false] +ExchangeSinkExec[[_doc{f}#0, salary{f}#1, hire_date{f}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, salary{f}, hire_date{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_Filter[salary{f} > 10000[INTEGER]] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#0, salary{f}#1, hire_date{f}#2]] +\_TopN[[Order[hire_date{f}#2,ASC,LAST]],20[INTEGER],false] + \_Filter[salary{f}#1 > 10000[INTEGER]] + \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#2, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#1, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected index 23b988ef09a77..178d31ccc5dc1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] - \_FieldExtractExec[emp_no{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, salary{f}, hire_date{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0]<[],[]> + \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#3, salary{f}#2, hire_date{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected index f356ac8daa272..6fc12a53e3980 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}, salary{f}, emp_no{f}]] -\_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}, hire_date{f}, salary{f}],false] +ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] +\_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, hire_date{f}, salary{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_Filter[salary{f} > 10000[INTEGER]] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] +\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] + \_Filter[salary{f}#1 > 10000[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected index 723ce904e88d3..fb387032f3d2a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[_doc{f}, hire_date{f}],false] -\_ProjectExec[[_doc{f}, hire_date{f}]] - \_FieldExtractExec[hire_date{f}]<[],[]> - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[[FieldSort[field=hire_date{f}, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] +\_ProjectExec[[_doc{f}#0, hire_date{f}#1]] + \_FieldExtractExec[hire_date{f}#1]<[],[]> + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected index 391e45f5b0835..9db0da8910f5b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}, hire_date{f}],false] +ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, hire_date{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#0, hire_date{f}#1]] +\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#1, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected index 89b94a06e2096..3c81025a6c14e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[hire_date{f}, salary{f}],false] -\_ProjectExec[[hire_date{f}, salary{f}]] - \_FieldExtractExec[salary{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],32] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file +ExchangeSinkExec[[hire_date{f}#0, salary{f}#1],false] +\_ProjectExec[[hire_date{f}#0, salary{f}#1]] + \_FieldExtractExec[salary{f}#1]<[],[]> + \_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],32] + \_ExchangeSourceExec[[_doc{f}#2, hire_date{f}#0],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected index 861afa9e16c8f..d520dec0664bd 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected @@ -1,10 +1,10 @@ -ProjectExec[[avg_salary{r}, count{r}]] -\_EvalExec[[$$SUM$avg_salary$0{r$} / $$COUNT$avg_salary$1{r$} AS avg_salary]] +ProjectExec[[avg_salary{r}#0, count{r}#1]] +\_EvalExec[[$$SUM$avg_salary$0{r$}#2 / $$COUNT$avg_salary$1{r$}#3 AS avg_salary#0]] \_LimitExec[10000[INTEGER],null] - \_AggregateExec[[],[SUM(salary{f},true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS $$SUM$avg_salary$0, COUNT(salary{f},true[BOOLEAN],PT0S[TIME_DURATION]) AS $$COUNT$avg_salary$1, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count],SINGLE,[$$SUM$avg_salary$0$sum{r}, $$SUM$avg_salary$0$seen{r}, $$COUNT$avg_salary$1$count{r}, $$COUNT$avg_salary$1$seen{r}, $$count$count{r}, $$count$seen{r}],null] - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[hire_date{f}, salary{f}],false] + \_AggregateExec[[],[SUM(salary{f}#4,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS $$SUM$avg_salary$0#2, COUNT(salary{f}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS $$COUNT$avg_salary$1#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count#1],SINGLE,[$$SUM$avg_salary$0$sum{r}#5, $$SUM$avg_salary$0$seen{r}#6, $$COUNT$avg_salary$1$count{r}#7, $$COUNT$avg_salary$1$seen{r}#8, $$count$count{r}#9, $$count$seen{r}#10],null] + \_TopNExec[[Order[hire_date{f}#11,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[hire_date{f}#11, salary{f}#4],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[hire_date{f}, salary{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[hire_date{f}#11, salary{f}#4]] +\_TopN[[Order[hire_date{f}#11,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}#12, birth_date{f}#13, emp_no{f}#14, first_name{f}#15, gender{f}#16, height{f}#17, height.float{f}#18, height.half_float{f}#19, height.scaled_float{f}#20, hire_date{f}#11, is_rehired{f}#21, job_positions{f}#22, languages{f}#23, languages.byte{f}#24, languages.long{f}#25, languages.short{f}#26, last_name{f}#27, salary{f}#4, salary_change{f}#28, salary_change.int{f}#29, salary_change.keyword{f}#30, salary_change.long{f}#31, still_hired{f}#32]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected index 5aa4ef96b07c0..80a4e9f155b81 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[_doc{f}, hire_date{f}],false] -\_ProjectExec[[_doc{f}, hire_date{r}]] - \_EvalExec[[null[DATETIME] AS hire_date]] - \_EsQueryExec[employees], indexMode[standard], [_doc{f}], limit[20], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file +ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] +\_ProjectExec[[_doc{f}#0, hire_date{r}#1]] + \_EvalExec[[null[DATETIME] AS hire_date#1]] + \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[20], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected index 391e45f5b0835..9db0da8910f5b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}, hire_date{f}],false] +ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}, hire_date{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][_doc{f}, avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[_doc{f}#0, hire_date{f}#1]] +\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#1, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected index 378271a5e3f37..4b4fc0c891ac1 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}, hire_date{f}, salary{f}],false] -\_ProjectExec[[emp_no{f}, hire_date{f}, salary{f}]] - \_FieldExtractExec[emp_no{f}, salary{f}]<[],[]> - \_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}, hire_date{f}],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] +\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] + \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> + \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected index cd76be3897e14..84b502cae4e25 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[hire_date{f}, salary{f}, emp_no{f}]] -\_TopNExec[[Order[hire_date{f},ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}, hire_date{f}, salary{f}],false] +ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] +\_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}, hire_date{f}, salary{f}]] -\_TopN[[Order[hire_date{f},ASC,LAST]],20[INTEGER],false] - \_EsRelation[employees][avg_worked_seconds{f}, birth_date{f}, emp_no{f}, first_name{f}, gender{f}, height{f}, height.float{f}, height.half_float{f}, height.scaled_float{f}, hire_date{f}, is_rehired{f}, job_positions{f}, languages{f}, languages.byte{f}, languages.long{f}, languages.short{f}, last_name{f}, salary{f}, salary_change{f}, salary_change.int{f}, salary_change.keyword{f}, salary_change.long{f}, still_hired{f}]<>]] \ No newline at end of file +Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] +\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file From 7e779c2baa27dffe4c768b524c99ba49a52f6818 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 9 Feb 2026 15:49:57 +0200 Subject: [PATCH 047/137] Prevent filter pushdown on potentially unmapped fields PotentiallyUnmappedKeywordEsField (used for fields loaded from _source when unmapped_fields="load") had isAggregatable=true, which caused isPushableFieldAttribute to short-circuit past the SearchStats check and push filters down to Lucene. On shards where the field is not indexed, the Lucene query returns no results instead of letting the compute engine evaluate the filter on _source-loaded values. Guard isPushableFieldAttribute against PotentiallyUnmappedKeywordEsField so these fields are always filtered in the compute engine. Co-authored-by: Cursor --- .../src/main/resources/unmapped-load.csv-spec | 81 ++++++++++++++----- .../local/LucenePushdownPredicates.java | 6 +- 2 files changed, 64 insertions(+), 23 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index b2fff4ffb70b2..0a3990c33c1fa 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -385,20 +385,20 @@ FROM partial_mapping_sample_data, sample_data METADATA _index | SORT @timestamp DESC ; -_index:keyword | @timestamp:datetime | foo:keyword | message:keyword | unmapped_message:keyword +_index:keyword | @timestamp:datetime | foo:keyword | message:keyword | unmapped_message:keyword partial_mapping_sample_data | 2024-10-23T13:55:01.543Z | null | Connected to 10.1.0.1! | Disconnected from 10.1.0.1 -partial_mapping_sample_data | 2024-10-23T13:53:55.832Z | null | Connection error? | Disconnection error -partial_mapping_sample_data | 2024-10-23T13:52:55.015Z | null | Connection error? | Disconnection error -partial_mapping_sample_data | 2024-10-23T13:51:54.732Z | null | Connection error? | Disconnection error -partial_mapping_sample_data | 2024-10-23T13:33:34.937Z | null | 42 | 43 +partial_mapping_sample_data | 2024-10-23T13:53:55.832Z | null | Connection error? | Disconnection error +partial_mapping_sample_data | 2024-10-23T13:52:55.015Z | null | Connection error? | Disconnection error +partial_mapping_sample_data | 2024-10-23T13:51:54.732Z | null | Connection error? | Disconnection error +partial_mapping_sample_data | 2024-10-23T13:33:34.937Z | null | 42 | 43 partial_mapping_sample_data | 2024-10-23T12:27:28.948Z | null | Connected to 10.1.0.2! | Disconnected from 10.1.0.2 partial_mapping_sample_data | 2024-10-23T12:15:03.360Z | null | Connected to 10.1.0.3! | Disconnected from 10.1.0.3 -sample_data | 2023-10-23T13:55:01.543Z | null | Connected to 10.1.0.1 | null -sample_data | 2023-10-23T13:53:55.832Z | null | Connection error | null -sample_data | 2023-10-23T13:52:55.015Z | null | Connection error | null -sample_data | 2023-10-23T13:51:54.732Z | null | Connection error | null -sample_data | 2023-10-23T13:33:34.937Z | null | Disconnected | null -sample_data | 2023-10-23T12:27:28.948Z | null | Connected to 10.1.0.2 | null +sample_data | 2023-10-23T13:55:01.543Z | null | Connected to 10.1.0.1 | null +sample_data | 2023-10-23T13:53:55.832Z | null | Connection error | null +sample_data | 2023-10-23T13:52:55.015Z | null | Connection error | null +sample_data | 2023-10-23T13:51:54.732Z | null | Connection error | null +sample_data | 2023-10-23T13:33:34.937Z | null | Disconnected | null +sample_data | 2023-10-23T12:27:28.948Z | null | Connected to 10.1.0.2 | null sample_data | 2023-10-23T12:15:03.360Z | null | Connected to 10.1.0.3 | null ; @@ -413,20 +413,20 @@ FROM partial_mapping_sample_data, sample_data METADATA _index | SORT @timestamp DESC ; -_index:keyword | @timestamp:datetime | foo:keyword | message:keyword | unmapped_message:keyword +_index:keyword | @timestamp:datetime | foo:keyword | message:keyword | unmapped_message:keyword partial_mapping_sample_data | 2024-10-23T13:55:01.543Z | null | Connected to 10.1.0.1! | Disconnected from 10.1.0.1 -partial_mapping_sample_data | 2024-10-23T13:53:55.832Z | null | Connection error? | Disconnection error -partial_mapping_sample_data | 2024-10-23T13:52:55.015Z | null | Connection error? | Disconnection error -partial_mapping_sample_data | 2024-10-23T13:51:54.732Z | null | Connection error? | Disconnection error -partial_mapping_sample_data | 2024-10-23T13:33:34.937Z | null | 42 | 43 +partial_mapping_sample_data | 2024-10-23T13:53:55.832Z | null | Connection error? | Disconnection error +partial_mapping_sample_data | 2024-10-23T13:52:55.015Z | null | Connection error? | Disconnection error +partial_mapping_sample_data | 2024-10-23T13:51:54.732Z | null | Connection error? | Disconnection error +partial_mapping_sample_data | 2024-10-23T13:33:34.937Z | null | 42 | 43 partial_mapping_sample_data | 2024-10-23T12:27:28.948Z | null | Connected to 10.1.0.2! | Disconnected from 10.1.0.2 partial_mapping_sample_data | 2024-10-23T12:15:03.360Z | null | Connected to 10.1.0.3! | Disconnected from 10.1.0.3 -sample_data | 2023-10-23T13:55:01.543Z | null | Connected to 10.1.0.1 | null -sample_data | 2023-10-23T13:53:55.832Z | null | Connection error | null -sample_data | 2023-10-23T13:52:55.015Z | null | Connection error | null -sample_data | 2023-10-23T13:51:54.732Z | null | Connection error | null -sample_data | 2023-10-23T13:33:34.937Z | null | Disconnected | null -sample_data | 2023-10-23T12:27:28.948Z | null | Connected to 10.1.0.2 | null +sample_data | 2023-10-23T13:55:01.543Z | null | Connected to 10.1.0.1 | null +sample_data | 2023-10-23T13:53:55.832Z | null | Connection error | null +sample_data | 2023-10-23T13:52:55.015Z | null | Connection error | null +sample_data | 2023-10-23T13:51:54.732Z | null | Connection error | null +sample_data | 2023-10-23T13:33:34.937Z | null | Disconnected | null +sample_data | 2023-10-23T12:27:28.948Z | null | Connected to 10.1.0.2 | null sample_data | 2023-10-23T12:15:03.360Z | null | Connected to 10.1.0.3 | null ; @@ -729,3 +729,40 @@ count(*):long | message::INT:integer 13 | null 1 | 42 ; + +fieldAliasAndNonExistent +required_capability: unmapped_fields +required_capability: optional_fields +required_capability: field_alias_support + +SET unmapped_fields="load"\; +FROM all_types +| KEEP integer, alias_integer, does_not_exist +| SORT integer +; + +integer:integer | alias_integer:integer | does_not_exist:keyword +1 | 1 | null +2 | 2 | null +3 | 3 | null +4 | 4 | null +5 | 5 | null +; + +filterOnPartiallyUnmappedField +required_capability: index_metadata_field +required_capability: unmapped_fields +required_capability: optional_fields + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| KEEP _index, message +| WHERE message == "Connection error?" +| SORT _index +; + +_index:keyword | message:keyword +no_mapping_sample_data | Connection error? +no_mapping_sample_data | Connection error? +no_mapping_sample_data | Connection error? +; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/LucenePushdownPredicates.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/LucenePushdownPredicates.java index aa9ea3b0e004b..3bb67a9a5c8f3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/LucenePushdownPredicates.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/LucenePushdownPredicates.java @@ -15,6 +15,7 @@ import org.elasticsearch.xpack.esql.core.expression.MetadataAttribute; import org.elasticsearch.xpack.esql.core.expression.TypedAttribute; import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.core.type.PotentiallyUnmappedKeywordEsField; import org.elasticsearch.xpack.esql.core.util.Check; import org.elasticsearch.xpack.esql.plugin.EsqlFlags; import org.elasticsearch.xpack.esql.stats.SearchStats; @@ -82,7 +83,10 @@ public interface LucenePushdownPredicates { * support it, and relying on the compute engine for the nodes that do not. */ default boolean isPushableFieldAttribute(Expression exp) { - if (exp instanceof FieldAttribute fa && fa.getExactInfo().hasExact() && isIndexedAndHasDocValues(fa)) { + if (exp instanceof FieldAttribute fa + && fa.field() instanceof PotentiallyUnmappedKeywordEsField == false + && fa.getExactInfo().hasExact() + && isIndexedAndHasDocValues(fa)) { return fa.dataType() != DataType.TEXT || hasExactSubfield(fa); } return false; From d526c11e60b4ab03853c3fbe62887ce0f1f09f1d Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 9 Feb 2026 16:14:43 +0200 Subject: [PATCH 048/137] Add test for sort pushdown on partially unmapped fields (#141925) The isPushableFieldAttribute fix (rejecting PotentiallyUnmappedKeywordEsField) already covers sort pushdown since PushTopNToSource uses the same method. This test verifies correct sort order when a field is mapped in one index but unmapped in another under unmapped_fields="load". Co-authored-by: Cursor --- .../src/main/resources/unmapped-load.csv-spec | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index 0a3990c33c1fa..d373dd71d0542 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -766,3 +766,23 @@ no_mapping_sample_data | Connection error? no_mapping_sample_data | Connection error? no_mapping_sample_data | Connection error? ; + +sortOnPartiallyUnmappedField +required_capability: index_metadata_field +required_capability: unmapped_fields +required_capability: optional_fields + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| KEEP _index, message +| SORT message, _index +| LIMIT 5 +; + +_index:keyword | message:keyword +no_mapping_sample_data | 42 +sample_data | Connected to 10.1.0.1 +no_mapping_sample_data | Connected to 10.1.0.1! +sample_data | Connected to 10.1.0.2 +no_mapping_sample_data | Connected to 10.1.0.2! +; From 8c3a2abbee1c76ca699d8c13a6f5982bf2b8554c Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 9 Feb 2026 16:25:39 +0200 Subject: [PATCH 049/137] Fix sort pushdown test to actually exercise the bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove _index from the SORT clause — it prevented the entire sort from being pushed to Lucene (canPushDownOrders requires all fields pushable), masking the bug. With only SORT message, the sort is pushed down and produces wrong order on the unmapped shard without the fix. Co-authored-by: Cursor --- .../qa/testFixtures/src/main/resources/unmapped-load.csv-spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index d373dd71d0542..86974629db487 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -775,7 +775,7 @@ required_capability: optional_fields SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data METADATA _index | KEEP _index, message -| SORT message, _index +| SORT message | LIMIT 5 ; From 979b2281c17a08867c97e75e71d7540ba64a1ace Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 18 Feb 2026 22:34:06 +0200 Subject: [PATCH 050/137] Add PushdownGoldenTests for sort and filter pushdown coverage. Capture single-index unmapped behavior for nullify/load and switch GoldenTestCase to read unmapped settings from parsed statements so SET-based golden tests run like type_conflicts. Co-authored-by: Cursor Made-with: Cursor --- .../xpack/esql/optimizer/GoldenTestCase.java | 13 ++-- .../esql/optimizer/PushdownGoldenTests.java | 64 +++++++++++++++++++ .../load/local_physical_optimization.expected | 9 +++ .../local_physical_optimization.expected | 1 + .../query.esql | 4 ++ .../local_physical_optimization.expected | 19 ++++++ .../testFilterPushdownNoUnmapped/query.esql | 4 ++ .../load/local_physical_optimization.expected | 8 +++ .../local_physical_optimization.expected | 8 +++ .../testSortNoPushdownWithUnmapped/query.esql | 4 ++ .../local_physical_optimization.expected | 6 ++ .../testSortPushdownNoUnmapped/query.esql | 4 ++ 12 files changed, 139 insertions(+), 5 deletions(-) create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/local_physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/nullify/local_physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/local_physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/load/local_physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/nullify/local_physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortPushdownNoUnmapped/local_physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortPushdownNoUnmapped/query.esql diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 8db76ff979eaa..65aa83642742f 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -25,14 +25,15 @@ import org.elasticsearch.xpack.esql.analysis.Analyzer; import org.elasticsearch.xpack.esql.analysis.AnalyzerContext; import org.elasticsearch.xpack.esql.analysis.EnrichResolution; -import org.elasticsearch.xpack.esql.analysis.UnmappedResolution; import org.elasticsearch.xpack.esql.core.expression.FoldContext; import org.elasticsearch.xpack.esql.core.tree.Node; import org.elasticsearch.xpack.esql.expression.function.EsqlFunctionRegistry; import org.elasticsearch.xpack.esql.inference.InferenceResolution; import org.elasticsearch.xpack.esql.parser.EsqlParser; +import org.elasticsearch.xpack.esql.plan.EsqlStatement; import org.elasticsearch.xpack.esql.plan.QueryPlan; import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; +import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.esql.plan.physical.ExchangeExec; import org.elasticsearch.xpack.esql.plan.physical.ExchangeSinkExec; import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; @@ -69,6 +70,7 @@ import static org.elasticsearch.xpack.esql.EsqlTestUtils.randomMinimumVersion; import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.defaultLookupResolution; +import static org.elasticsearch.xpack.esql.plan.QuerySettings.UNMAPPED_FIELDS; /** See GoldenTestsReadme.md for more information about these tests. */ @Listeners({ GoldenTestCase.GoldenTestReproduceInfoPrinter.class }) @@ -200,24 +202,25 @@ private void doTest() { } private List> doTests() throws IOException { - LogicalPlan parsedStatement = EsqlParser.INSTANCE.parseQuery(esqlQuery); + EsqlStatement statement = EsqlParser.INSTANCE.createStatement(esqlQuery); + LogicalPlan parsedPlan = statement.plan(); Files.createDirectories(PathUtils.get(basePath.toString(), testName)); Files.writeString(PathUtils.get(basePath.toString(), testName, "query.esql"), esqlQuery); var analyzer = new Analyzer( new AnalyzerContext( EsqlTestUtils.TEST_CFG, new EsqlFunctionRegistry(), - CsvTests.loadIndexResolution(CsvTests.testDatasets(parsedStatement)), + CsvTests.loadIndexResolution(CsvTests.testDatasets(parsedPlan)), defaultLookupResolution(), new EnrichResolution(), InferenceResolution.EMPTY, transportVersion, - UnmappedResolution.FAIL + statement.setting(UNMAPPED_FIELDS) ), TEST_VERIFIER ); List> result = new ArrayList<>(); - var analyzed = analyzer.analyze(parsedStatement); + var analyzed = analyzer.analyze(parsedPlan); if (stages.contains(Stage.ANALYSIS)) { result.add(Tuple.tuple(Stage.ANALYSIS, verifyOrWrite(analyzed, Stage.ANALYSIS))); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java new file mode 100644 index 0000000000000..87a271a588cf3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.optimizer; + +import org.elasticsearch.xpack.esql.action.EsqlCapabilities; + +import java.util.EnumSet; + +public class PushdownGoldenTests extends GoldenTestCase { + private static final EnumSet STAGES = EnumSet.of(Stage.LOCAL_PHYSICAL_OPTIMIZATION); + + public void testFilterPushdownNoUnmapped() { + String query = """ + FROM sample_data + | KEEP message + | WHERE message == "Connection error?" + | SORT message + """; + runGoldenTest(query, STAGES); + } + + public void testFilterNoPushdownWithUnmapped() { + String query = """ + FROM sample_data + | KEEP message, does_not_exist + | WHERE does_not_exist::KEYWORD == "Connection error?" + | SORT message + """; + runUnmappedTests(query); + } + + + public void testSortPushdownNoUnmapped() { + String query = """ + FROM sample_data + | KEEP message + | SORT message + | LIMIT 5 + """; + runGoldenTest(query, STAGES); + } + + public void testSortNoPushdownWithUnmapped() { + String query = """ + FROM sample_data + | KEEP message, does_not_exist + | SORT does_not_exist + | LIMIT 5 + """; + runUnmappedTests(query); + } + + private void runUnmappedTests(String query) { + assumeTrue("Requires OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW", EsqlCapabilities.Cap.OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW.isEnabled()); + assumeTrue("Requires OPTIONAL_FIELDS", EsqlCapabilities.Cap.OPTIONAL_FIELDS.isEnabled()); + runGoldenTest("SET unmapped_fields=\"nullify\"; " + query, STAGES, "nullify"); + runGoldenTest("SET unmapped_fields=\"load\"; " + query, STAGES, "load"); + } +} diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/local_physical_optimization.expected new file mode 100644 index 0000000000000..e2e7295fcd58b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/local_physical_optimization.expected @@ -0,0 +1,9 @@ +ProjectExec[[message{f}#0, does_not_exist{f}#1]] +\_TopNExec[[Order[message{f}#0,ASC,LAST]],1000[INTEGER],null] + \_ExchangeExec[[message{f}#0, does_not_exist{f}#1],false] + \_ProjectExec[[message{f}#0, does_not_exist{f}#1]] + \_TopNExec[[Order[message{f}#0,ASC,LAST]],1000[INTEGER],120] + \_FieldExtractExec[message{f}#0]<[],[]> + \_FilterExec[TOSTRING(does_not_exist{f}#1) == Connection error?[KEYWORD]] + \_FieldExtractExec[does_not_exist{f}#1]<[],[]> + \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#2], limit[], sort[] estimatedRowSize[104] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/nullify/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/nullify/local_physical_optimization.expected new file mode 100644 index 0000000000000..8f0caf6cc39a3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/nullify/local_physical_optimization.expected @@ -0,0 +1 @@ +LocalSourceExec[[message{f}#0, does_not_exist{r}#1],EMPTY] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/query.esql new file mode 100644 index 0000000000000..a9e7be32bea23 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM sample_data +| KEEP message, does_not_exist +| WHERE does_not_exist::KEYWORD == "Connection error?" +| SORT message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/local_physical_optimization.expected new file mode 100644 index 0000000000000..0a984515a2d68 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/local_physical_optimization.expected @@ -0,0 +1,19 @@ +ProjectExec[[message{f}#0]] +\_TopNExec[[Order[message{f}#0,ASC,LAST]],1000[INTEGER],null] + \_ExchangeExec[[message{f}#0],false] + \_ProjectExec[[message{f}#0]] + \_FieldExtractExec[message{f}#0]<[],[]> + \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#1], limit[1000], sort[[FieldSort[field=message{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query={ + "esql_single_value" : { + "field" : "message", + "next" : { + "term" : { + "message" : { + "value" : "Connection error?", + "boost" : 0.0 + } + } + }, + "source" : "message == \"Connection error?\"@3:9" + } +}, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/query.esql new file mode 100644 index 0000000000000..bf24ea983bcb5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/query.esql @@ -0,0 +1,4 @@ +FROM sample_data +| KEEP message +| WHERE message == "Connection error?" +| SORT message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/load/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/load/local_physical_optimization.expected new file mode 100644 index 0000000000000..ac325cce5294d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/load/local_physical_optimization.expected @@ -0,0 +1,8 @@ +ProjectExec[[message{f}#0, does_not_exist{f}#1]] +\_TopNExec[[Order[does_not_exist{f}#1,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[message{f}#0, does_not_exist{f}#1],false] + \_ProjectExec[[message{f}#0, does_not_exist{f}#1]] + \_FieldExtractExec[message{f}#0]<[],[]> + \_TopNExec[[Order[does_not_exist{f}#1,ASC,LAST]],5[INTEGER],120] + \_FieldExtractExec[does_not_exist{f}#1]<[],[]> + \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#2], limit[], sort[] estimatedRowSize[54] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/nullify/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/nullify/local_physical_optimization.expected new file mode 100644 index 0000000000000..ea4e1b4e5134b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/nullify/local_physical_optimization.expected @@ -0,0 +1,8 @@ +ProjectExec[[message{f}#0, does_not_exist{r}#1]] +\_TopNExec[[Order[does_not_exist{r}#1,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[message{f}#0, does_not_exist{r}#1],false] + \_ProjectExec[[message{f}#0, does_not_exist{r}#1]] + \_FieldExtractExec[message{f}#0]<[],[]> + \_TopNExec[[Order[does_not_exist{r}#1,ASC,LAST]],5[INTEGER],70] + \_EvalExec[[null[NULL] AS does_not_exist#1]] + \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#2], limit[], sort[] estimatedRowSize[4] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/query.esql new file mode 100644 index 0000000000000..57c8258095508 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM sample_data +| KEEP message, does_not_exist +| SORT does_not_exist +| LIMIT 5 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortPushdownNoUnmapped/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortPushdownNoUnmapped/local_physical_optimization.expected new file mode 100644 index 0000000000000..f758f6bba7277 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortPushdownNoUnmapped/local_physical_optimization.expected @@ -0,0 +1,6 @@ +ProjectExec[[message{f}#0]] +\_TopNExec[[Order[message{f}#0,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[message{f}#0],false] + \_ProjectExec[[message{f}#0]] + \_FieldExtractExec[message{f}#0]<[],[]> + \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#1], limit[5], sort[[FieldSort[field=message{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortPushdownNoUnmapped/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortPushdownNoUnmapped/query.esql new file mode 100644 index 0000000000000..5f079d6daad40 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortPushdownNoUnmapped/query.esql @@ -0,0 +1,4 @@ +FROM sample_data +| KEEP message +| SORT message +| LIMIT 5 From b1c00f4759503537087117e47d40806265d01888 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 3 Mar 2026 14:06:43 +0200 Subject: [PATCH 051/137] Update docs/changelog/143460.yaml --- docs/changelog/143460.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/changelog/143460.yaml diff --git a/docs/changelog/143460.yaml b/docs/changelog/143460.yaml new file mode 100644 index 0000000000000..082eda2e68ed9 --- /dev/null +++ b/docs/changelog/143460.yaml @@ -0,0 +1,6 @@ +area: ES|QL +issues: + - 141920 +pr: 143460 +summary: Prevent pushdown of unmapped fields in filters and sorts +type: "bug, feature" From b67dc4fe2128788a010da4c74588d41849a1f2c6 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Tue, 3 Mar 2026 12:13:35 +0000 Subject: [PATCH 052/137] [CI] Auto commit changes from spotless --- .../org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java | 1 - .../elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java | 1 - 2 files changed, 2 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 65aa83642742f..7148b79cd74be 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -33,7 +33,6 @@ import org.elasticsearch.xpack.esql.plan.EsqlStatement; import org.elasticsearch.xpack.esql.plan.QueryPlan; import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; -import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.esql.plan.physical.ExchangeExec; import org.elasticsearch.xpack.esql.plan.physical.ExchangeSinkExec; import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java index 87a271a588cf3..c2cad2986981d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java @@ -34,7 +34,6 @@ public void testFilterNoPushdownWithUnmapped() { runUnmappedTests(query); } - public void testSortPushdownNoUnmapped() { String query = """ FROM sample_data From 8669a61d74cf08518b0ce159f86357f9bb02026f Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 3 Mar 2026 15:00:11 +0200 Subject: [PATCH 053/137] CR: Decompose, deduplicate --- .../xpack/esql/optimizer/GoldenTestCase.java | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 7148b79cd74be..0465305805a97 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -61,6 +61,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.BiFunction; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -389,29 +390,20 @@ private static Test.TestResult createNewOutput(Path output, QueryPlan plan) t if (output.toString().contains("extra")) { throw new IllegalStateException("Extra output files should not be created automatically:" + output); } - Files.writeString(output, normalizeNameIds(plan), StandardCharsets.UTF_8); + String full = plan.toString(Node.NodeStringFormat.FULL); + Files.writeString(output, normalizeNameIds(normalizeSyntheticNames(full)), StandardCharsets.UTF_8); return Test.TestResult.CREATED; } /** * Rewrites node IDs ({@code #n}) in the plan string to a stable numbering by order of first appearance. - * Actual IDs assi;ned during plan building can vary between runs, so this is needed to keep golden output deterministic. + * Actual IDs assigned during plan building can vary between runs, so this is needed to keep golden output deterministic. */ - private static String normalizeNameIds(Node plan) { - String full = plan.toString(Node.NodeStringFormat.FULL); - String normalized = normalizeSyntheticNames(full); - Matcher matcher = IDENTIFIER_PATTERN.matcher(normalized); - StringBuilder sb = new StringBuilder(); - int lastEnd = 0; - var idMap = new IdMap(); - while (matcher.find()) { - sb.append(normalized, lastEnd, matcher.start()); + private static String normalizeNameIds(String planString) { + return replaceMatches(planString, IDENTIFIER_PATTERN, (matcher, idMap) -> { int originalId = Integer.parseInt(matcher.group().substring(1)); // Drop the initial '#' prefix - sb.append("#").append(idMap.getId(originalId)); - lastEnd = matcher.end(); - } - sb.append(normalized, lastEnd, normalized.length()); - return sb.toString(); + return "#" + idMap.getId(originalId); + }); } /** @@ -419,17 +411,23 @@ private static String normalizeNameIds(Node plan) { * Replaces them with $$firstSegment$runningInt so golden output is stable across runs. */ private static String normalizeSyntheticNames(String full) { - Matcher matcher = SYNTHETIC_PATTERN.matcher(full); + return replaceMatches(full, SYNTHETIC_PATTERN, (matcher, idMap) -> { + String firstSegment = matcher.group(1); + return "$$" + firstSegment + "$" + idMap.getId(firstSegment); + }); + } + + private static String replaceMatches(String input, Pattern pattern, BiFunction, String> replacer) { + var idMap = new IdMap(); + Matcher matcher = pattern.matcher(input); StringBuilder sb = new StringBuilder(); int lastEnd = 0; - var idMap = new IdMap(); while (matcher.find()) { - sb.append(full, lastEnd, matcher.start()); - String firstSegment = matcher.group(1); - sb.append("$$").append(firstSegment).append("$").append(idMap.getId(firstSegment)); + sb.append(input, lastEnd, matcher.start()); + sb.append(replacer.apply(matcher, idMap)); lastEnd = matcher.end(); } - sb.append(full, lastEnd, full.length()); + sb.append(input, lastEnd, input.length()); return sb.toString(); } @@ -448,7 +446,8 @@ public int getId(K key) { } private static Test.TestResult verifyExisting(Path output, QueryPlan plan) throws IOException { - String testString = normalize(normalizeNameIds(plan)); + String full = plan.toString(Node.NodeStringFormat.FULL); + String testString = normalize(normalizeNameIds(normalizeSyntheticNames(full))); if (testString.equals(normalize(Files.readString(output)))) { if (System.getProperty("golden.cleanactual") != null) { Path path = actualPath(output); From d2f1dbcbf90d4ef5ae290853f16b79c6e820df3b Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 3 Mar 2026 16:41:35 +0200 Subject: [PATCH 054/137] Address Alex's PR #143460 review comments - Add OPTIONAL_FIELDS_V2 capability for pushdown-elimination BWC. - Remove fieldAliasAndNonExistent test; fix capabilities on pushdown tests. - Remove SORT from filterOnPartiallyUnmappedField; add fully unmapped multi-sort, and cast tests in unmapped-load.csv-spec. - Add comment in LucenePushdownPredicates for PotentiallyUnmappedKeywordEsField. - Add cross-refs between PushdownGoldenTests and LocalPhysicalPlanOptimizerTests. - Fix assumeTrue: use OPTIONAL_FIELDS_V2 for load, remove redundant nullify. - Write query.esql to nested path in GoldenTestCase. This was actually a pretty "noisy" change, since it also affect SubstituteRoundToGoldenTests! - Add filter-only, conjunction pushable/non-pushable golden tests. Made-with: Cursor --- .../src/main/resources/unmapped-load.csv-spec | 280 ++++++++++++++---- .../xpack/esql/action/EsqlCapabilities.java | 11 +- .../local/LucenePushdownPredicates.java | 2 + .../xpack/esql/plan/QuerySettings.java | 4 +- .../esql/analysis/AnalyzerUnmappedTests.java | 2 +- .../xpack/esql/optimizer/GoldenTestCase.java | 9 +- .../LocalPhysicalPlanOptimizerTests.java | 6 +- .../esql/optimizer/PushdownGoldenTests.java | 46 ++- .../xpack/esql/parser/SetParserTests.java | 4 +- .../xpack/esql/plan/QuerySettingsTests.java | 2 +- .../load/local_physical_optimization.expected | 22 ++ .../load/query.esql | 3 + .../local_physical_optimization.expected | 1 + .../nullify/query.esql | 3 + .../load/local_physical_optimization.expected | 8 + .../load/query.esql | 3 + .../local_physical_optimization.expected | 20 ++ .../nullify/query.esql | 3 + .../load/local_physical_optimization.expected | 6 +- .../{ => load}/query.esql | 1 - .../nullify/query.esql | 3 + .../local_physical_optimization.expected | 4 +- .../testFilterPushdownNoUnmapped/query.esql | 1 - .../local_physical_optimization.expected | 19 ++ .../query.esql | 3 + .../load/local_physical_optimization.expected | 7 + .../load/query.esql | 4 + .../local_physical_optimization.expected | 7 + .../nullify/query.esql | 4 + .../{ => load}/query.esql | 0 .../nullify/query.esql | 4 + .../bucket/query.esql | 4 + .../date_trunc/query.esql | 4 + .../{ => round_to}/query.esql | 0 .../bucket/query.esql | 4 + .../date_trunc/query.esql | 4 + .../{ => round_to}/query.esql | 0 .../bucket/query.esql | 2 + .../date_trunc/query.esql | 2 + .../{ => round_to}/query.esql | 0 .../bucket/query.esql | 2 + .../date_trunc/query.esql | 2 + .../{ => round_to}/query.esql | 0 .../bucket/query.esql | 2 + .../date_trunc/query.esql | 2 + .../{ => round_to}/query.esql | 0 .../bucket/date_range/query.esql | 3 + .../bucket/keyword_equality/query.esql | 3 + .../bucket/keyword_match/query.esql | 3 + .../date_trunc/date_range/query.esql | 3 + .../date_trunc/keyword_equality/query.esql | 3 + .../date_trunc/keyword_match/query.esql | 3 + .../round_to/date_range/query.esql | 3 + .../round_to/keyword_equality/query.esql | 3 + .../{ => round_to/keyword_match}/query.esql | 0 .../bucket/query.esql | 2 + .../date_trunc/query.esql | 2 + .../{ => round_to}/query.esql | 0 .../date_trunc/query.esql | 5 + .../{ => round_to}/query.esql | 0 .../byte/query.esql | 2 + .../date/query.esql | 2 + .../date_nanos/query.esql | 2 + .../double/query.esql | 2 + .../float/query.esql | 2 + .../half_float/query.esql | 2 + .../integer/query.esql | 2 + .../{ => long}/query.esql | 0 .../scaled_float/query.esql | 2 + .../short/query.esql | 2 + 70 files changed, 494 insertions(+), 77 deletions(-) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/load/local_physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/load/local_physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/{ => load}/query.esql (89%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmappedFilterOnly/local_physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmappedFilterOnly/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/load/local_physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/nullify/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/{ => load}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/{ => round_to}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/{ => round_to}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/{ => round_to}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/{ => round_to}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/{ => round_to}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/{ => round_to/keyword_match}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/{ => round_to}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/{ => round_to}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/query.esql rename x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/{ => long}/query.esql (100%) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/query.esql diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index 86974629db487..35a3a7503d107 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -101,7 +101,7 @@ FROM partial_mapping_sample_data fieldIsMappedToNonKeywordSingleIndex required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -121,7 +121,7 @@ FROM partial_mapping_sample_data fieldIsMappedToKeywordSingleIndex required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -141,7 +141,7 @@ FROM partial_mapping_sample_data unmappedFieldDoesNotAppearLast required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -155,7 +155,7 @@ FROM partial_mapping_sample_data fieldDoesNotExistSingleIndex required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -175,7 +175,7 @@ FROM partial_mapping_sample_data fieldIsUnmappedSingleIndex required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -198,7 +198,7 @@ FROM partial_mapping_sample_data fieldIsUnmappedButSourceIsDisabledSingleIndex-Ignore required_capability: source_field_mapping required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_no_source_sample_data @@ -218,7 +218,7 @@ FROM partial_mapping_no_source_sample_data fieldIsUnmappedButExcludedFromSourceSingleIndex-Ignore required_capability: source_field_mapping required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_excluded_source_sample_data @@ -237,7 +237,7 @@ FROM partial_mapping_excluded_source_sample_data fieldIsNestedAndMapped required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM addresses @@ -253,7 +253,7 @@ Amsterdam fieldIsNestedAndMappedNoKeep required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM addresses @@ -268,7 +268,7 @@ Europe |Milky Way |Earth fieldIsNestedAndUnmapped required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -288,7 +288,7 @@ FROM partial_mapping_sample_data fieldIsNestedAndNonExistent required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -312,7 +312,7 @@ FROM partial_mapping_sample_data noFieldExistsMultiParametersSingleIndex required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -332,7 +332,7 @@ FROM partial_mapping_sample_data mixedFieldsMultiParametersSingleIndex required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -352,7 +352,7 @@ FROM partial_mapping_sample_data repeatedInsistFieldsUseTheLastEntry required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -377,7 +377,7 @@ FROM partial_mapping_sample_data mixedFieldsMultiParametersMultiIndex required_capability: unmapped_fields required_capability: index_metadata_field -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data, sample_data METADATA _index @@ -405,7 +405,7 @@ sample_data | 2023-10-23T12:15:03.360Z | null | Connected insistOnTopOfInsistMultiIndex required_capability: unmapped_fields required_capability: index_metadata_field -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data, sample_data METADATA _index @@ -433,7 +433,7 @@ sample_data | 2023-10-23T12:15:03.360Z | null | Connected fieldDoesNotExistMultiIndex required_capability: index_metadata_field required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data, sample_data METADATA _index @@ -461,7 +461,7 @@ sample_data | 2023-10-23T12:15:03.360Z | null fieldIsUnmappedMultiIndex required_capability: index_metadata_field required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data, sample_data METADATA _index @@ -490,7 +490,7 @@ FROM partial_mapping_sample_data, sample_data METADATA _index fieldIsMappedToDifferentTypesMultiIndex required_capability: index_metadata_field required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM sample_data_ts_long, sample_data METADATA _index @@ -518,7 +518,7 @@ sample_data_ts_long | null fieldIsMappedToDifferentTypesButDropped required_capability: index_metadata_field required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM sample_data_ts_long, sample_data METADATA _index @@ -548,7 +548,7 @@ sample_data_ts_long | 42 fieldIsPartiallyUnmappedMultiIndex required_capability: index_metadata_field required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data METADATA _index @@ -575,7 +575,7 @@ sample_data | Connected to 10.1.0.1 fieldIsPartiallyUnmappedAndRenamedMultiIndex required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data @@ -605,7 +605,7 @@ fieldIsPartiallyUnmappedPartiallySourceIsDisabledMultiIndex required_capability: index_metadata_field required_capability: source_field_mapping required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data,partial_mapping_no_source_sample_data METADATA _index @@ -634,7 +634,7 @@ partialMappingStats required_capability: index_metadata_field required_capability: source_field_mapping required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data,partial_mapping_excluded_source_sample_data METADATA _index @@ -655,7 +655,7 @@ partialMappingCoalesce required_capability: index_metadata_field required_capability: source_field_mapping required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data,partial_mapping_excluded_source_sample_data METADATA _index @@ -686,7 +686,7 @@ partialMappingUnionTypes required_capability: index_metadata_field required_capability: source_field_mapping required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data,partial_mapping_excluded_source_sample_data METADATA _index @@ -716,7 +716,7 @@ partialMappingStatsAfterCast required_capability: index_metadata_field required_capability: source_field_mapping required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM partial_mapping_sample_data,partial_mapping_excluded_source_sample_data @@ -730,38 +730,20 @@ count(*):long | message::INT:integer 1 | 42 ; -fieldAliasAndNonExistent -required_capability: unmapped_fields -required_capability: optional_fields -required_capability: field_alias_support - -SET unmapped_fields="load"\; -FROM all_types -| KEEP integer, alias_integer, does_not_exist -| SORT integer -; - -integer:integer | alias_integer:integer | does_not_exist:keyword -1 | 1 | null -2 | 2 | null -3 | 3 | null -4 | 4 | null -5 | 5 | null -; - filterOnPartiallyUnmappedField required_capability: index_metadata_field -required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data METADATA _index | KEEP _index, message -| WHERE message == "Connection error?" -| SORT _index +| WHERE STARTS_WITH(message, "Connection error") ; _index:keyword | message:keyword +sample_data | Connection error +sample_data | Connection error +sample_data | Connection error no_mapping_sample_data | Connection error? no_mapping_sample_data | Connection error? no_mapping_sample_data | Connection error? @@ -769,8 +751,7 @@ no_mapping_sample_data | Connection error? sortOnPartiallyUnmappedField required_capability: index_metadata_field -required_capability: unmapped_fields -required_capability: optional_fields +required_capability: optional_fields_v2 SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data METADATA _index @@ -786,3 +767,198 @@ no_mapping_sample_data | Connected to 10.1.0.1! sample_data | Connected to 10.1.0.2 no_mapping_sample_data | Connected to 10.1.0.2! ; + +filterOnFullyUnmappedField +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM partial_mapping_sample_data +| KEEP @timestamp, unmapped_message +| WHERE unmapped_message == "Disconnection error" +; + +@timestamp:date | unmapped_message:keyword +2024-10-23T13:53:55.832Z | Disconnection error +2024-10-23T13:52:55.015Z | Disconnection error +2024-10-23T13:51:54.732Z | Disconnection error +; + +filterOnConjunctionMappedAndUnmapped +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM partial_mapping_sample_data +| KEEP @timestamp, message, unmapped_message +| WHERE message == "Connection error?" AND unmapped_message == "Disconnection error" +; + +@timestamp:date | message:keyword | unmapped_message:keyword +2024-10-23T13:53:55.832Z | Connection error? | Disconnection error +2024-10-23T13:52:55.015Z | Connection error? | Disconnection error +2024-10-23T13:51:54.732Z | Connection error? | Disconnection error +; + +filterOnConjunctionMappedAndNonExistent +required_capability: index_metadata_field +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| KEEP _index, message, does_not_exist +| WHERE message == "Connection error" AND does_not_exist == "x" +; + +_index:keyword | message:keyword | does_not_exist:keyword +; + +filterOnDisjunctionMappedAndUnmapped +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM partial_mapping_sample_data +| KEEP @timestamp, message, unmapped_message +| WHERE message == "42" OR unmapped_message == "Disconnection error" +| SORT @timestamp +; + +@timestamp:date | message:keyword | unmapped_message:keyword +2024-10-23T13:33:34.937Z | 42 | 43 +2024-10-23T13:51:54.732Z | Connection error? | Disconnection error +2024-10-23T13:52:55.015Z | Connection error? | Disconnection error +2024-10-23T13:53:55.832Z | Connection error? | Disconnection error +; + +filterOnDisjunctionMappedAndNonExistent +required_capability: index_metadata_field +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| KEEP _index, message, does_not_exist +| WHERE message == "Connection error" OR does_not_exist == "x" +| SORT _index, message +; + +_index:keyword | message:keyword | does_not_exist:keyword +sample_data | Connection error | null +sample_data | Connection error | null +sample_data | Connection error | null +; + +sortOnNonExistentField +required_capability: index_metadata_field +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM no_mapping_sample_data METADATA _index +| KEEP _index, does_not_exist +| SORT does_not_exist, _index +| LIMIT 5 +; + +_index:keyword | does_not_exist:keyword +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +; + +sortOnUnmappedField +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM partial_mapping_sample_data +| KEEP @timestamp, unmapped_message +| SORT unmapped_message +| LIMIT 5 +; + +@timestamp:date | unmapped_message:keyword +2024-10-23T13:33:34.937Z | 43 +2024-10-23T13:55:01.543Z | Disconnected from 10.1.0.1 +2024-10-23T12:27:28.948Z | Disconnected from 10.1.0.2 +2024-10-23T12:15:03.360Z | Disconnected from 10.1.0.3 +2024-10-23T13:52:55.015Z | Disconnection error +; + +sortOnExpressionOnUnmappedField +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM partial_mapping_sample_data +| KEEP @timestamp, unmapped_message +| SORT LENGTH(unmapped_message), @timestamp +| LIMIT 5 +; + +@timestamp:date | unmapped_message:keyword +2024-10-23T13:33:34.937Z | 43 +2024-10-23T13:51:54.732Z | Disconnection error +2024-10-23T13:52:55.015Z | Disconnection error +2024-10-23T13:53:55.832Z | Disconnection error +2024-10-23T12:15:03.360Z | Disconnected from 10.1.0.3 +; + +sortOnMultipleFieldsWithNonExistent +required_capability: index_metadata_field +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| KEEP _index, message, does_not_exist +| SORT message, does_not_exist +| LIMIT 5 +; + +_index:keyword | message:keyword | does_not_exist:keyword +no_mapping_sample_data | 42 | null +sample_data | Connected to 10.1.0.1 | null +no_mapping_sample_data | Connected to 10.1.0.1! | null +sample_data | Connected to 10.1.0.2 | null +no_mapping_sample_data | Connected to 10.1.0.2! | null +; + +sortOnMultipleFieldsWithUnmapped +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM partial_mapping_sample_data +| KEEP @timestamp, message, unmapped_message +| SORT message, unmapped_message, @timestamp +| LIMIT 5 +; + +@timestamp:datetime | message:keyword | unmapped_message:keyword +2024-10-23T13:33:34.937Z | 42 | 43 +2024-10-23T13:55:01.543Z | Connected to 10.1.0.1! | Disconnected from 10.1.0.1 +2024-10-23T12:27:28.948Z | Connected to 10.1.0.2! | Disconnected from 10.1.0.2 +2024-10-23T12:15:03.360Z | Connected to 10.1.0.3! | Disconnected from 10.1.0.3 +2024-10-23T13:51:54.732Z | Connection error? | Disconnection error +; + +filterOnNonExistentFieldCastToLong +required_capability: index_metadata_field +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| KEEP _index, message, does_not_exist +| WHERE does_not_exist::long == 42 +; + +_index:keyword | message:keyword | does_not_exist:keyword +; + +filterOnUnmappedFieldCastToLong +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM partial_mapping_sample_data +| KEEP @timestamp, message, unmapped_event_duration +| WHERE unmapped_event_duration::long == 725449 +; + +@timestamp:date | message:keyword | unmapped_event_duration:keyword +2024-10-23T13:51:54.732Z | Connection error? | 725449 +; 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 73c21701bc6fb..49981e5ee468d 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 @@ -167,17 +167,18 @@ public enum Cap { */ METADATA_FIELDS, - /** - * Support for optional fields (might or might not be present in the mappings) using FAIL/NULLIFY/LOAD - */ - OPTIONAL_FIELDS(Build.current().isSnapshot()), - /** * Support for Optional fields (might or might not be present in the mappings) using FAIL/NULLIFY only. This is a temporary * capability until we enable the LOAD option mentioned above. */ OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW, + /** + * Support for optional fields (might or might not be present in the mappings) using FAIL/NULLIFY/LOAD. + * V2: prevent pushing down filters and sorts to Lucene of potentially unmapped fields. + */ + OPTIONAL_FIELDS_V2(Build.current().isSnapshot()), + /** * Support specifically for *just* the _index METADATA field. Used by CsvTests, since that is the only metadata field currently * supported. diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/LucenePushdownPredicates.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/LucenePushdownPredicates.java index 3bb67a9a5c8f3..8726e8a46d4f5 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/LucenePushdownPredicates.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/LucenePushdownPredicates.java @@ -83,6 +83,8 @@ public interface LucenePushdownPredicates { * support it, and relying on the compute engine for the nodes that do not. */ default boolean isPushableFieldAttribute(Expression exp) { + // Potentially unmapped fields are not pushabled: the field may be unmapped on some shards, and pushing down would produce wrong + // results (e.g., missing rows when the predicate is pushed to Lucene). if (exp instanceof FieldAttribute fa && fa.field() instanceof PotentiallyUnmappedKeywordEsField == false && fa.getExactInfo().hasExact() diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/QuerySettings.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/QuerySettings.java index bb9a7c991eed1..17c33d26bf67e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/QuerySettings.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/QuerySettings.java @@ -95,12 +95,12 @@ public class QuerySettings { String resolution = Foldables.stringLiteralValueOf(value, "Unexpected value"); try { UnmappedResolution res = UnmappedResolution.valueOf(resolution.toUpperCase(Locale.ROOT)); - if (res == UnmappedResolution.LOAD && EsqlCapabilities.Cap.OPTIONAL_FIELDS.isEnabled() == false) { + if (res == UnmappedResolution.LOAD && EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled() == false) { throw new IllegalArgumentException("'LOAD' is only supported in snapshot builds"); } return res; } catch (Exception exc) { - var values = EsqlCapabilities.Cap.OPTIONAL_FIELDS.isEnabled() + var values = EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled() ? UnmappedResolution.values() : Arrays.stream(UnmappedResolution.values()).filter(e -> e != UnmappedResolution.LOAD).toArray(); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index 2e628d677182b..d7b0cc348d227 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -3465,7 +3465,7 @@ private static String setUnmappedNullify(String query) { } private static String setUnmappedLoad(String query) { - assumeTrue("Requires OPTIONAL_FIELDS", EsqlCapabilities.Cap.OPTIONAL_FIELDS.isEnabled()); + assumeTrue("Requires OPTIONAL_FIELDS_V2", EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled()); return "SET unmapped_fields=\"load\"; " + query; } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 0465305805a97..1bfb7e7a301ae 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -204,8 +204,13 @@ private void doTest() { private List> doTests() throws IOException { EsqlStatement statement = EsqlParser.INSTANCE.createStatement(esqlQuery); LogicalPlan parsedPlan = statement.plan(); - Files.createDirectories(PathUtils.get(basePath.toString(), testName)); - Files.writeString(PathUtils.get(basePath.toString(), testName, "query.esql"), esqlQuery); + String[] queryPathParts = new String[nestedPath.length + 2]; + queryPathParts[0] = testName; + System.arraycopy(nestedPath, 0, queryPathParts, 1, nestedPath.length); + queryPathParts[queryPathParts.length - 1] = "query.esql"; + Path queryPath = PathUtils.get(basePath.toString(), queryPathParts); + Files.createDirectories(queryPath.getParent()); + Files.writeString(queryPath, esqlQuery); var analyzer = new Analyzer( new AnalyzerContext( EsqlTestUtils.TEST_CFG, diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java index 8ef40a9caf979..a47c86ad60fb0 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java @@ -134,7 +134,11 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -//@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE,org.elasticsearch.compute:TRACE", reason = "debug") +/** + * Unit tests for local physical plan optimization rules. For pushdown-related tests (filter, sort), + * prefer adding new cases to {@link PushdownGoldenTests} instead. + */ +// @TestLogging(value = "org.elasticsearch.xpack.esql:TRACE,org.elasticsearch.compute:TRACE", reason = "debug") public class LocalPhysicalPlanOptimizerTests extends AbstractLocalPhysicalPlanOptimizerTests { public static final List UNNECESSARY_CASTING_DATA_TYPES = List.of( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java index c2cad2986981d..0a40ac6df2600 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java @@ -11,6 +11,10 @@ import java.util.EnumSet; +/** + * Golden tests for filter and sort pushdown to Lucene. + * New pushdown tests should be added here rather than in {@link LocalPhysicalPlanOptimizerTests}. + */ public class PushdownGoldenTests extends GoldenTestCase { private static final EnumSet STAGES = EnumSet.of(Stage.LOCAL_PHYSICAL_OPTIMIZATION); @@ -19,7 +23,15 @@ public void testFilterPushdownNoUnmapped() { FROM sample_data | KEEP message | WHERE message == "Connection error?" - | SORT message + """; + runGoldenTest(query, STAGES); + } + + public void testFilterPushdownNoUnmappedFilterOnly() { + String query = """ + FROM sample_data + | KEEP message + | WHERE message == "Connection error?" """; runGoldenTest(query, STAGES); } @@ -29,7 +41,6 @@ public void testFilterNoPushdownWithUnmapped() { FROM sample_data | KEEP message, does_not_exist | WHERE does_not_exist::KEYWORD == "Connection error?" - | SORT message """; runUnmappedTests(query); } @@ -54,10 +65,37 @@ public void testSortNoPushdownWithUnmapped() { runUnmappedTests(query); } + public void testFilterConjunctionPushableAndNonPushable() { + String query = """ + FROM sample_data + | KEEP message, does_not_exist + | WHERE message == "Connection error?" AND does_not_exist::KEYWORD == "foo" + """; + runUnmappedTests(query); + } + + public void testFilterDisjunctionPushableAndNonPushable() { + String query = """ + FROM sample_data + | KEEP message, does_not_exist + | WHERE message == "Connection error?" OR does_not_exist::KEYWORD == "foo" + """; + runUnmappedTests(query); + } + + public void testSortConjunctionPushableAndNonPushable() { + String query = """ + FROM sample_data + | KEEP message, does_not_exist + | SORT message, does_not_exist + | LIMIT 5 + """; + runUnmappedTests(query); + } + private void runUnmappedTests(String query) { - assumeTrue("Requires OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW", EsqlCapabilities.Cap.OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW.isEnabled()); - assumeTrue("Requires OPTIONAL_FIELDS", EsqlCapabilities.Cap.OPTIONAL_FIELDS.isEnabled()); runGoldenTest("SET unmapped_fields=\"nullify\"; " + query, STAGES, "nullify"); + assumeTrue("Requires OPTIONAL_FIELDS_V2 for load", EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled()); runGoldenTest("SET unmapped_fields=\"load\"; " + query, STAGES, "load"); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/SetParserTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/SetParserTests.java index fefbf21fc9943..598713ed116b3 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/SetParserTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/SetParserTests.java @@ -199,7 +199,7 @@ private Object settingValue(EsqlStatement query, int position) { } public void testSetUnmappedFields_snapshot() { - assumeTrue("OPTIONAL_FIELDS option required", EsqlCapabilities.Cap.OPTIONAL_FIELDS.isEnabled()); + assumeTrue("OPTIONAL_FIELDS_V2 option required", EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled()); var modes = List.of("FAIL", "NULLIFY", "LOAD"); verifySetUnmappedFields(modes); @@ -236,7 +236,7 @@ public void testSetUnmappedFieldsWrongValue() { v -> Arrays.stream(UnmappedResolution.values()).anyMatch(x -> x.name().equalsIgnoreCase(v)), () -> randomAlphaOfLengthBetween(0, 10) ); - var values = EsqlCapabilities.Cap.OPTIONAL_FIELDS.isEnabled() + var values = EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled() ? UnmappedResolution.values() : Arrays.stream(UnmappedResolution.values()).filter(e -> e != UnmappedResolution.LOAD).toArray(); expectValidationError( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plan/QuerySettingsTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plan/QuerySettingsTests.java index 954d5ff446389..95ad271935e53 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plan/QuerySettingsTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plan/QuerySettingsTests.java @@ -114,7 +114,7 @@ public void testValidate_UnmappedFields_techPreview() { } public void testValidate_UnmappedFields_allValues() { - assumeTrue("Requires unmapped fields", EsqlCapabilities.Cap.OPTIONAL_FIELDS.isEnabled()); + assumeTrue("Requires unmapped fields", EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled()); validateUnmappedFields("FAIL", "NULLIFY", "LOAD"); } diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/load/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/load/local_physical_optimization.expected new file mode 100644 index 0000000000000..2f56604505197 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/load/local_physical_optimization.expected @@ -0,0 +1,22 @@ +ProjectExec[[message{f}#0, does_not_exist{f}#1]] +\_LimitExec[1000[INTEGER],null] + \_ExchangeExec[[message{f}#0, does_not_exist{f}#1],false] + \_ProjectExec[[message{f}#0, does_not_exist{f}#1]] + \_FieldExtractExec[message{f}#0]<[],[]> + \_LimitExec[1000[INTEGER],70] + \_FilterExec[TOSTRING(does_not_exist{f}#1) == foo[KEYWORD]] + \_FieldExtractExec[does_not_exist{f}#1]<[],[]> + \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#2], limit[], sort[] estimatedRowSize[104] queryBuilderAndTags [[QueryBuilderAndTags[query={ + "esql_single_value" : { + "field" : "message", + "next" : { + "term" : { + "message" : { + "value" : "Connection error?", + "boost" : 0.0 + } + } + }, + "source" : "message == \"Connection error?\"@3:9" + } +}, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/load/query.esql new file mode 100644 index 0000000000000..aae3d123cd59d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM sample_data +| KEEP message, does_not_exist +| WHERE message == "Connection error?" AND does_not_exist::KEYWORD == "foo" diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected new file mode 100644 index 0000000000000..8f0caf6cc39a3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected @@ -0,0 +1 @@ +LocalSourceExec[[message{f}#0, does_not_exist{r}#1],EMPTY] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/nullify/query.esql new file mode 100644 index 0000000000000..90dfe77b22995 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM sample_data +| KEEP message, does_not_exist +| WHERE message == "Connection error?" AND does_not_exist::KEYWORD == "foo" diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/load/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/load/local_physical_optimization.expected new file mode 100644 index 0000000000000..b3ff975b660ee --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/load/local_physical_optimization.expected @@ -0,0 +1,8 @@ +ProjectExec[[message{f}#0, does_not_exist{f}#1]] +\_LimitExec[1000[INTEGER],null] + \_ExchangeExec[[message{f}#0, does_not_exist{f}#1],false] + \_ProjectExec[[message{f}#0, does_not_exist{f}#1]] + \_LimitExec[1000[INTEGER],120] + \_FilterExec[message{f}#0 == Connection error?[KEYWORD] OR TOSTRING(does_not_exist{f}#1) == foo[KEYWORD]] + \_FieldExtractExec[message{f}#0, does_not_exist{f}#1]<[],[]> + \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#2], limit[], sort[] estimatedRowSize[104] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/load/query.esql new file mode 100644 index 0000000000000..c2356bab45ce1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM sample_data +| KEEP message, does_not_exist +| WHERE message == "Connection error?" OR does_not_exist::KEYWORD == "foo" diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected new file mode 100644 index 0000000000000..e43a2df780fed --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected @@ -0,0 +1,20 @@ +ProjectExec[[message{f}#0, does_not_exist{r}#1]] +\_EvalExec[[null[NULL] AS does_not_exist#1]] + \_LimitExec[1000[INTEGER],null] + \_ExchangeExec[[message{f}#0],false] + \_ProjectExec[[message{f}#0]] + \_FieldExtractExec[message{f}#0]<[],[]> + \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#2], limit[1000], sort[] estimatedRowSize[54] queryBuilderAndTags [[QueryBuilderAndTags[query={ + "esql_single_value" : { + "field" : "message", + "next" : { + "term" : { + "message" : { + "value" : "Connection error?", + "boost" : 0.0 + } + } + }, + "source" : "message == \"Connection error?\"@3:9" + } +}, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/nullify/query.esql new file mode 100644 index 0000000000000..2468c7df0cecb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM sample_data +| KEEP message, does_not_exist +| WHERE message == "Connection error?" OR does_not_exist::KEYWORD == "foo" diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/local_physical_optimization.expected index e2e7295fcd58b..89814d11149b2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/local_physical_optimization.expected @@ -1,9 +1,9 @@ ProjectExec[[message{f}#0, does_not_exist{f}#1]] -\_TopNExec[[Order[message{f}#0,ASC,LAST]],1000[INTEGER],null] +\_LimitExec[1000[INTEGER],null] \_ExchangeExec[[message{f}#0, does_not_exist{f}#1],false] \_ProjectExec[[message{f}#0, does_not_exist{f}#1]] - \_TopNExec[[Order[message{f}#0,ASC,LAST]],1000[INTEGER],120] - \_FieldExtractExec[message{f}#0]<[],[]> + \_FieldExtractExec[message{f}#0]<[],[]> + \_LimitExec[1000[INTEGER],70] \_FilterExec[TOSTRING(does_not_exist{f}#1) == Connection error?[KEYWORD]] \_FieldExtractExec[does_not_exist{f}#1]<[],[]> \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#2], limit[], sort[] estimatedRowSize[104] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/query.esql similarity index 89% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/query.esql index a9e7be32bea23..4ee238720afc0 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/query.esql @@ -1,4 +1,3 @@ SET unmapped_fields="load"; FROM sample_data | KEEP message, does_not_exist | WHERE does_not_exist::KEYWORD == "Connection error?" -| SORT message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..f4dca580d6f03 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM sample_data +| KEEP message, does_not_exist +| WHERE does_not_exist::KEYWORD == "Connection error?" diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/local_physical_optimization.expected index 0a984515a2d68..aa4715e3b0414 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/local_physical_optimization.expected @@ -1,9 +1,9 @@ ProjectExec[[message{f}#0]] -\_TopNExec[[Order[message{f}#0,ASC,LAST]],1000[INTEGER],null] +\_LimitExec[1000[INTEGER],null] \_ExchangeExec[[message{f}#0],false] \_ProjectExec[[message{f}#0]] \_FieldExtractExec[message{f}#0]<[],[]> - \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#1], limit[1000], sort[[FieldSort[field=message{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query={ + \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#1], limit[1000], sort[] estimatedRowSize[54] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "message", "next" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/query.esql index bf24ea983bcb5..3f0beb4863e4c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/query.esql +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/query.esql @@ -1,4 +1,3 @@ FROM sample_data | KEEP message | WHERE message == "Connection error?" -| SORT message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmappedFilterOnly/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmappedFilterOnly/local_physical_optimization.expected new file mode 100644 index 0000000000000..aa4715e3b0414 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmappedFilterOnly/local_physical_optimization.expected @@ -0,0 +1,19 @@ +ProjectExec[[message{f}#0]] +\_LimitExec[1000[INTEGER],null] + \_ExchangeExec[[message{f}#0],false] + \_ProjectExec[[message{f}#0]] + \_FieldExtractExec[message{f}#0]<[],[]> + \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#1], limit[1000], sort[] estimatedRowSize[54] queryBuilderAndTags [[QueryBuilderAndTags[query={ + "esql_single_value" : { + "field" : "message", + "next" : { + "term" : { + "message" : { + "value" : "Connection error?", + "boost" : 0.0 + } + } + }, + "source" : "message == \"Connection error?\"@3:9" + } +}, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmappedFilterOnly/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmappedFilterOnly/query.esql new file mode 100644 index 0000000000000..3f0beb4863e4c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmappedFilterOnly/query.esql @@ -0,0 +1,3 @@ +FROM sample_data +| KEEP message +| WHERE message == "Connection error?" diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/load/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/load/local_physical_optimization.expected new file mode 100644 index 0000000000000..d7739a31c30d2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/load/local_physical_optimization.expected @@ -0,0 +1,7 @@ +ProjectExec[[message{f}#0, does_not_exist{f}#1]] +\_TopNExec[[Order[message{f}#0,ASC,LAST], Order[does_not_exist{f}#1,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[message{f}#0, does_not_exist{f}#1],false] + \_ProjectExec[[message{f}#0, does_not_exist{f}#1]] + \_TopNExec[[Order[message{f}#0,ASC,LAST], Order[does_not_exist{f}#1,ASC,LAST]],5[INTEGER],120] + \_FieldExtractExec[message{f}#0, does_not_exist{f}#1]<[],[]> + \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#2], limit[], sort[] estimatedRowSize[104] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/load/query.esql new file mode 100644 index 0000000000000..57c17b605f339 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM sample_data +| KEEP message, does_not_exist +| SORT message, does_not_exist +| LIMIT 5 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected new file mode 100644 index 0000000000000..3dac4b94f8e4b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected @@ -0,0 +1,7 @@ +ProjectExec[[message{f}#0, does_not_exist{r}#1]] +\_TopNExec[[Order[message{f}#0,ASC,LAST], Order[does_not_exist{r}#1,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[message{f}#0, does_not_exist{r}#1],false] + \_ProjectExec[[message{f}#0, does_not_exist{r}#1]] + \_FieldExtractExec[message{f}#0]<[],[]> + \_EvalExec[[null[NULL] AS does_not_exist#1]] + \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#2], limit[5], sort[[FieldSort[field=message{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/nullify/query.esql new file mode 100644 index 0000000000000..49722710b90bd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM sample_data +| KEEP message, does_not_exist +| SORT message, does_not_exist +| LIMIT 5 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/load/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/load/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..8fd945997a09c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM sample_data +| KEEP message, does_not_exist +| SORT does_not_exist +| LIMIT 5 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/query.esql new file mode 100644 index 0000000000000..b615c9c44e290 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/query.esql @@ -0,0 +1,4 @@ +from all_types +| fork (where integer > 100) +(where keyword : "keyword") +| stats count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/query.esql new file mode 100644 index 0000000000000..58c5f6728342c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/query.esql @@ -0,0 +1,4 @@ +from all_types +| fork (where integer > 100) +(where keyword : "keyword") +| stats count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/query.esql new file mode 100644 index 0000000000000..f24a6518c3f51 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/query.esql @@ -0,0 +1,4 @@ +from all_types +| rename integer as language_code +| lookup join languages_lookup on language_code +| stats count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/query.esql new file mode 100644 index 0000000000000..74629dcb51051 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/query.esql @@ -0,0 +1,4 @@ +from all_types +| rename integer as language_code +| lookup join languages_lookup on language_code +| stats count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/query.esql new file mode 100644 index 0000000000000..22fca42d878fd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/bucket/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/query.esql new file mode 100644 index 0000000000000..fa1300117c2a8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/date_trunc/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/round_to/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTags/round_to/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/query.esql new file mode 100644 index 0000000000000..22fca42d878fd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/bucket/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/query.esql new file mode 100644 index 0000000000000..fa1300117c2a8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/date_trunc/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/round_to/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithEsFilter/round_to/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/query.esql new file mode 100644 index 0000000000000..54b417415ee19 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats sum(long), count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/query.esql new file mode 100644 index 0000000000000..c9af83d6cbaac --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats sum(long), count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/query.esql new file mode 100644 index 0000000000000..d57165bff1599 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/date_range/query.esql @@ -0,0 +1,3 @@ +from all_types +| where date >= "2023-10-19" and date <= "2023-10-24" +| stats count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/query.esql new file mode 100644 index 0000000000000..b6ffb3562cf48 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/query.esql @@ -0,0 +1,3 @@ +from all_types +| where keyword == "keyword" +| stats count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/query.esql new file mode 100644 index 0000000000000..1b177e943af0f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/query.esql @@ -0,0 +1,3 @@ +from all_types +| where keyword : "keyword" +| stats count(*) by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/query.esql new file mode 100644 index 0000000000000..c6afebcab13d7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/date_range/query.esql @@ -0,0 +1,3 @@ +from all_types +| where date >= "2023-10-19" and date <= "2023-10-24" +| stats count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/query.esql new file mode 100644 index 0000000000000..031813404bc12 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/query.esql @@ -0,0 +1,3 @@ +from all_types +| where keyword == "keyword" +| stats count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/query.esql new file mode 100644 index 0000000000000..3c3cbc238870b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/query.esql @@ -0,0 +1,3 @@ +from all_types +| where keyword : "keyword" +| stats count(*) by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/query.esql new file mode 100644 index 0000000000000..c56287a3dee3f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/date_range/query.esql @@ -0,0 +1,3 @@ +from all_types +| where date >= "2023-10-19" and date <= "2023-10-24" +| stats count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/query.esql new file mode 100644 index 0000000000000..0e2c6e873cf48 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/query.esql @@ -0,0 +1,3 @@ +from all_types +| where keyword == "keyword" +| stats count(*) by x = round_to(date, "2023-10-20", "2023-10-21", "2023-10-22", "2023-10-23") diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/query.esql new file mode 100644 index 0000000000000..6309500488457 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) where long > 10 by x = bucket(date, 1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/query.esql new file mode 100644 index 0000000000000..039fd5ff287a6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) where long > 10 by x = date_trunc(1 day, date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/query.esql new file mode 100644 index 0000000000000..6756737f704e2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/query.esql @@ -0,0 +1,5 @@ +from all_types +| sort date +| eval x = date_trunc(1 day, date) +| keep alias_integer, date, x +| limit 5 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/query.esql new file mode 100644 index 0000000000000..883ffe342e7d4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/byte/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(byte, 2,1,3,4) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/query.esql new file mode 100644 index 0000000000000..2f79776c6dda5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(date, "2023-10-20"::date,"2023-10-21"::date,"2023-10-22"::date,"2023-10-23"::date) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/query.esql new file mode 100644 index 0000000000000..ed625ca873010 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/date_nanos/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(date_nanos, "2023-10-20"::date_nanos,"2023-10-21"::date_nanos,"2023-10-22"::date_nanos,"2023-10-23"::date_nanos) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/query.esql new file mode 100644 index 0000000000000..c4de6bf1e06a3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/double/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(double, 1.0,2.0,3.0,4.0) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/query.esql new file mode 100644 index 0000000000000..1d66674da19c1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/float/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(float, 3.0,2.0,1.0,4.0) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/query.esql new file mode 100644 index 0000000000000..eb1740cb34fd4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/half_float/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(half_float, 4.0,2.0,3.0,1.0) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/query.esql new file mode 100644 index 0000000000000..347e5c1c1f33e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/integer/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(integer, 1,2,3,4) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/long/query.esql similarity index 100% rename from x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/query.esql rename to x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/long/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/query.esql new file mode 100644 index 0000000000000..bc01ac6cabd48 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/scaled_float/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(scaled_float, 4.0,3.0,2.0,1.0) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/query.esql new file mode 100644 index 0000000000000..f9618eba09919 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testRoundToTransformToQueryAndTags/short/query.esql @@ -0,0 +1,2 @@ +from all_types +| stats count(*) by x = round_to(short, 1,3,2,4) From 6545746d4af304a2156acee556437cdcaeaad40a Mon Sep 17 00:00:00 2001 From: Ievgen Degtiarenko Date: Tue, 3 Mar 2026 11:27:14 +0100 Subject: [PATCH 055/137] Cleanup SpecIT logging configuration (#143365) --- .../xpack/esql/qa/multi_node/EsqlSpecIT.java | 6 +----- .../xpack/esql/qa/single_node/Clusters.java | 10 ---------- .../xpack/esql/qa/single_node/EsqlSpecIT.java | 5 +++-- .../xpack/esql/qa/single_node/GenerativeForkIT.java | 3 +-- 4 files changed, 5 insertions(+), 19 deletions(-) diff --git a/x-pack/plugin/esql/qa/server/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/multi_node/EsqlSpecIT.java b/x-pack/plugin/esql/qa/server/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/multi_node/EsqlSpecIT.java index 427f6460005fd..5ac5e06fc38f1 100644 --- a/x-pack/plugin/esql/qa/server/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/multi_node/EsqlSpecIT.java +++ b/x-pack/plugin/esql/qa/server/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/multi_node/EsqlSpecIT.java @@ -13,15 +13,11 @@ import org.junit.ClassRule; import java.io.IOException; -import java.util.Map; public class EsqlSpecIT extends EsqlSpecTestCase { @ClassRule public static ElasticsearchCluster cluster = Clusters.testCluster(spec -> { - spec.plugin("inference-service-test"); - for (Map.Entry entry : LOGGING_CLUSTER_SETTINGS.entrySet()) { - spec.setting(entry.getKey(), entry.getValue()); - } + spec.plugin("inference-service-test").settings(nodeSpec -> LOGGING_CLUSTER_SETTINGS); }); @Override diff --git a/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/Clusters.java b/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/Clusters.java index 9a476d23fccdc..cca5138c8d403 100644 --- a/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/Clusters.java +++ b/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/Clusters.java @@ -9,11 +9,7 @@ import org.elasticsearch.test.cluster.ElasticsearchCluster; import org.elasticsearch.test.cluster.local.LocalClusterConfigProvider; -import org.elasticsearch.test.cluster.local.LocalClusterSpecBuilder; import org.elasticsearch.test.cluster.local.distribution.DistributionType; -import org.elasticsearch.xpack.esql.qa.rest.EsqlSpecTestCase; - -import java.util.Map; public class Clusters { @@ -30,10 +26,4 @@ public static ElasticsearchCluster testCluster(LocalClusterConfigProvider config .apply(() -> configProvider) .build(); } - - public static void addAdditionalLoggingSettings(LocalClusterSpecBuilder spec) { - for (Map.Entry entry : EsqlSpecTestCase.LOGGING_CLUSTER_SETTINGS.entrySet()) { - spec.setting(entry.getKey(), entry.getValue()); - } - } } diff --git a/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlSpecIT.java b/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlSpecIT.java index 0bf8e4583a02e..c0f413317e9ae 100644 --- a/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlSpecIT.java +++ b/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlSpecIT.java @@ -28,8 +28,9 @@ public class EsqlSpecIT extends EsqlSpecTestCase { @ClassRule public static ElasticsearchCluster cluster = Clusters.testCluster(spec -> { - spec.plugin("inference-service-test").setting("logger." + ComputeService.class.getName(), "DEBUG"); // So we log a profile - Clusters.addAdditionalLoggingSettings(spec); + spec.plugin("inference-service-test") + .setting("logger." + ComputeService.class.getName(), "DEBUG") // So we log a profile + .settings(nodeSpec -> LOGGING_CLUSTER_SETTINGS); }); public EsqlSpecIT(String fileName, String groupName, String testName, Integer lineNumber, CsvTestCase testCase, String instructions) { diff --git a/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/GenerativeForkIT.java b/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/GenerativeForkIT.java index 83c6ab2aea877..b84636aeac4ef 100644 --- a/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/GenerativeForkIT.java +++ b/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/GenerativeForkIT.java @@ -19,8 +19,7 @@ public class GenerativeForkIT extends GenerativeForkRestTest { @ClassRule public static ElasticsearchCluster cluster = Clusters.testCluster(spec -> { - spec.plugin("inference-service-test"); - Clusters.addAdditionalLoggingSettings(spec); + spec.plugin("inference-service-test").settings(nodeSpec -> LOGGING_CLUSTER_SETTINGS); }); @Override From ed5b1773eb5e13aaec8f323eb128e0928ee3b926 Mon Sep 17 00:00:00 2001 From: Dimitris Rempapis Date: Tue, 3 Mar 2026 12:57:46 +0200 Subject: [PATCH 056/137] Add circuit breaker for query construction to prevent OOM from automaton-based queries (#142150) --- docs/changelog/142150.yaml | 6 + .../AccountableQueryCircuitBreakerIT.java | 197 ++++++++++++++++++ .../breaker/CircuitBreakerServiceIT.java | 82 +++++--- .../index/mapper/StringFieldType.java | 40 +++- .../index/query/RegexpQueryBuilder.java | 35 ++-- .../index/query/SearchExecutionContext.java | 59 +++++- .../search/DefaultSearchContext.java | 6 +- .../elasticsearch/search/SearchService.java | 16 +- .../index/query/PrefixQueryBuilderTests.java | 33 ++- .../query/QueryStringQueryBuilderTests.java | 18 ++ .../index/query/RangeQueryBuilderTests.java | 11 + .../index/query/RegexpQueryBuilderTests.java | 18 ++ .../query/WildcardQueryBuilderTests.java | 14 ++ .../search/DefaultSearchContextTests.java | 22 +- .../search/SearchServiceTests.java | 107 ++++++++++ .../test/AbstractBuilderTestCase.java | 96 ++++++++- .../esql/plugin/ComputeSearchContext.java | 1 + 17 files changed, 689 insertions(+), 72 deletions(-) create mode 100644 docs/changelog/142150.yaml create mode 100644 server/src/internalClusterTest/java/org/elasticsearch/indices/memory/breaker/AccountableQueryCircuitBreakerIT.java diff --git a/docs/changelog/142150.yaml b/docs/changelog/142150.yaml new file mode 100644 index 0000000000000..7e65e9729ff8f --- /dev/null +++ b/docs/changelog/142150.yaml @@ -0,0 +1,6 @@ +area: Search +issues: [] +pr: 142150 +summary: Add circuit breaker for query construction to prevent OOM from automaton-based + queries +type: bug diff --git a/server/src/internalClusterTest/java/org/elasticsearch/indices/memory/breaker/AccountableQueryCircuitBreakerIT.java b/server/src/internalClusterTest/java/org/elasticsearch/indices/memory/breaker/AccountableQueryCircuitBreakerIT.java new file mode 100644 index 0000000000000..6484cdd194c21 --- /dev/null +++ b/server/src/internalClusterTest/java/org/elasticsearch/indices/memory/breaker/AccountableQueryCircuitBreakerIT.java @@ -0,0 +1,197 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.indices.memory.breaker; + +import org.elasticsearch.action.admin.cluster.node.stats.NodeStats; +import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse; +import org.elasticsearch.action.index.IndexRequestBuilder; +import org.elasticsearch.action.search.SearchRequestBuilder; +import org.elasticsearch.common.breaker.CircuitBreaker; +import org.elasticsearch.common.breaker.NoopCircuitBreaker; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.PrefixQueryBuilder; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.index.query.QueryStringQueryBuilder; +import org.elasticsearch.index.query.RangeQueryBuilder; +import org.elasticsearch.index.query.RegexpQueryBuilder; +import org.elasticsearch.index.query.WildcardQueryBuilder; +import org.elasticsearch.indices.breaker.CircuitBreakerStats; +import org.elasticsearch.indices.breaker.HierarchyCircuitBreakerService; +import org.elasticsearch.rest.RestStatus; +import org.elasticsearch.test.ESIntegTestCase; +import org.elasticsearch.test.ESIntegTestCase.ClusterScope; +import org.junit.After; +import org.junit.Before; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.IntFunction; + +import static org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_NUMBER_OF_REPLICAS; +import static org.elasticsearch.test.ESIntegTestCase.Scope.TEST; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFailures; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; + +/** + * Integration tests verifying that Lucene queries implementing {@link org.apache.lucene.util.Accountable} + * (wildcard, prefix, regexp, query_string, range) are properly tracked by the request circuit breaker + * during query construction, and that the accounted memory is released after the search completes. + */ +@ClusterScope(scope = TEST, numClientNodes = 0, maxNumDataNodes = 1) +public class AccountableQueryCircuitBreakerIT extends ESIntegTestCase { + + private static final String INDEX_NAME = "cb-accountable-test"; + private static final String TEXT_FIELD = "text_field"; + private static final String KEYWORD_FIELD = "keyword_field"; + + @Before + public void checkBreakerType() { + assumeFalse("--> noop breakers used, skipping test", noopBreakerUsed()); + } + + @After + public void resetBreakerSettings() { + updateClusterSettings( + Settings.builder() + .putNull(HierarchyCircuitBreakerService.REQUEST_CIRCUIT_BREAKER_LIMIT_SETTING.getKey()) + .putNull(HierarchyCircuitBreakerService.REQUEST_CIRCUIT_BREAKER_OVERHEAD_SETTING.getKey()) + ); + } + + public void testWildcardQueryTripsCircuitBreaker() { + assertBoolQueryTripsBreaker(100, i -> new WildcardQueryBuilder(TEXT_FIELD, "*pattern*" + i + "*")); + } + + public void testPrefixQueryTripsCircuitBreaker() { + assertBoolQueryTripsBreaker(100, i -> new PrefixQueryBuilder(TEXT_FIELD, "prefix" + i)); + } + + public void testRegexpQueryTripsCircuitBreaker() { + assertBoolQueryTripsBreaker(50, i -> new RegexpQueryBuilder(TEXT_FIELD, "(pattern" + i + "|alternate" + i + "|option" + i + ").*")); + } + + public void testQueryStringTripsCircuitBreaker() { + assertBoolQueryTripsBreaker(100, i -> new QueryStringQueryBuilder("*pattern" + i + "*").defaultField(TEXT_FIELD)); + } + + public void testRangeQueryTripsCircuitBreaker() { + assertBoolQueryTripsBreaker(100, i -> new RangeQueryBuilder(KEYWORD_FIELD).gte("key" + i).lte("key" + (i + 100))); + } + + public void testWildcardQueryMemoryReleased() throws Exception { + assertQueryMemoryReleasedAfterSearch(new WildcardQueryBuilder(TEXT_FIELD, "*test*pattern*")); + } + + public void testPrefixQueryMemoryReleased() throws Exception { + assertQueryMemoryReleasedAfterSearch(new PrefixQueryBuilder(TEXT_FIELD, "value")); + } + + public void testRegexpQueryMemoryReleased() throws Exception { + assertQueryMemoryReleasedAfterSearch(new RegexpQueryBuilder(TEXT_FIELD, ".*test.*pattern.*")); + } + + public void testQueryStringMemoryReleased() throws Exception { + assertQueryMemoryReleasedAfterSearch(new QueryStringQueryBuilder("*test*pattern*").defaultField(TEXT_FIELD)); + } + + public void testRangeQueryMemoryReleased() throws Exception { + assertQueryMemoryReleasedAfterSearch(new RangeQueryBuilder(KEYWORD_FIELD).gte("key0").lte("key999")); + } + + private void assertBoolQueryTripsBreaker(int count, IntFunction queryFactory) { + createAndPopulateIndex(); + + BoolQueryBuilder boolQuery = new BoolQueryBuilder(); + for (int i = 0; i < count; i++) { + boolQuery.should(queryFactory.apply(i)); + } + assertQueryTripsBreaker(boolQuery); + } + + private void assertQueryMemoryReleasedAfterSearch(QueryBuilder query) throws Exception { + createAndPopulateIndex(); + assertQueryMemoryReleased(query); + } + + private boolean noopBreakerUsed() { + NodesStatsResponse stats = clusterAdmin().prepareNodesStats().setBreaker(true).get(); + for (NodeStats nodeStats : stats.getNodes()) { + if (nodeStats.getBreaker().getStats(CircuitBreaker.REQUEST).getLimit() == NoopCircuitBreaker.LIMIT) { + return true; + } + } + return false; + } + + private long getRequestBreakerTrippedCount() { + NodesStatsResponse stats = clusterAdmin().prepareNodesStats().setBreaker(true).get(); + long tripped = 0; + for (NodeStats stat : stats.getNodes()) { + CircuitBreakerStats breakerStats = stat.getBreaker().getStats(CircuitBreaker.REQUEST); + if (breakerStats != null) { + tripped += breakerStats.getTrippedCount(); + } + } + return tripped; + } + + private long getRequestBreakerEstimated() { + NodesStatsResponse stats = clusterAdmin().prepareNodesStats().setBreaker(true).get(); + long estimated = 0; + for (NodeStats stat : stats.getNodes()) { + CircuitBreakerStats breakerStats = stat.getBreaker().getStats(CircuitBreaker.REQUEST); + if (breakerStats != null) { + estimated += breakerStats.getEstimated(); + } + } + return estimated; + } + + private void createAndPopulateIndex() { + assertAcked( + prepareCreate(INDEX_NAME, 1, Settings.builder().put(SETTING_NUMBER_OF_REPLICAS, between(0, 1))).setMapping( + TEXT_FIELD, + "type=text", + KEYWORD_FIELD, + "type=keyword" + ) + ); + int docCount = scaledRandomIntBetween(100, 500); + List reqs = new ArrayList<>(); + for (long id = 0; id < docCount; id++) { + reqs.add( + client().prepareIndex(INDEX_NAME).setId(Long.toString(id)).setSource(TEXT_FIELD, "value" + id, KEYWORD_FIELD, "key" + id) + ); + } + indexRandom(true, false, true, reqs); + } + + private void assertQueryTripsBreaker(QueryBuilder query) { + updateClusterSettings( + Settings.builder() + .put(HierarchyCircuitBreakerService.REQUEST_CIRCUIT_BREAKER_LIMIT_SETTING.getKey(), "10b") + .put(HierarchyCircuitBreakerService.REQUEST_CIRCUIT_BREAKER_OVERHEAD_SETTING.getKey(), 1.0) + ); + + SearchRequestBuilder searchRequest = client().prepareSearch(INDEX_NAME).setQuery(query); + assertFailures(searchRequest, RestStatus.BAD_REQUEST, containsString("Data too large")); + assertThat("Request circuit breaker should have tripped", getRequestBreakerTrippedCount(), greaterThanOrEqualTo(1L)); + } + + private void assertQueryMemoryReleased(QueryBuilder query) throws Exception { + long baseline = getRequestBreakerEstimated(); + client().prepareSearch(INDEX_NAME).setQuery(query).get().decRef(); + long estimated = getRequestBreakerEstimated(); + assertEquals("Request breaker memory should be released after search completes", baseline, estimated); + } +} diff --git a/server/src/internalClusterTest/java/org/elasticsearch/indices/memory/breaker/CircuitBreakerServiceIT.java b/server/src/internalClusterTest/java/org/elasticsearch/indices/memory/breaker/CircuitBreakerServiceIT.java index 9beb3d0ef6c41..4fc00a07c432b 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/indices/memory/breaker/CircuitBreakerServiceIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/indices/memory/breaker/CircuitBreakerServiceIT.java @@ -28,6 +28,8 @@ import org.elasticsearch.common.unit.ByteSizeUnit; import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.core.TimeValue; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.WildcardQueryBuilder; import org.elasticsearch.indices.breaker.CircuitBreakerStats; import org.elasticsearch.indices.breaker.HierarchyCircuitBreakerService; import org.elasticsearch.rest.RestStatus; @@ -110,10 +112,7 @@ private boolean noopBreakerUsed() { } public void testMemoryBreaker() throws Exception { - if (noopBreakerUsed()) { - logger.info("--> noop breakers used, skipping test"); - return; - } + assumeFalse("--> noop breakers used, skipping test", noopBreakerUsed()); assertAcked( prepareCreate("cb-test", 1, Settings.builder().put(SETTING_NUMBER_OF_REPLICAS, between(0, 1))).setMapping( "test", @@ -159,10 +158,7 @@ public void testMemoryBreaker() throws Exception { } public void testRamAccountingTermsEnum() throws Exception { - if (noopBreakerUsed()) { - logger.info("--> noop breakers used, skipping test"); - return; - } + assumeFalse("--> noop breakers used, skipping test", noopBreakerUsed()); final Client client = client(); // Create an index where the mappings have a field data filter @@ -225,10 +221,7 @@ public void testRamAccountingTermsEnum() throws Exception { } public void testRequestBreaker() throws Exception { - if (noopBreakerUsed()) { - logger.info("--> noop breakers used, skipping test"); - return; - } + assumeFalse("--> noop breakers used, skipping test", noopBreakerUsed()); assertAcked(prepareCreate("cb-test", 1, Settings.builder().put(SETTING_NUMBER_OF_REPLICAS, between(0, 1)))); Client client = client(); @@ -256,10 +249,7 @@ public void testRequestBreaker() throws Exception { } public void testAggTookTooMuch() throws Exception { - if (noopBreakerUsed()) { - logger.info("--> noop breakers used, skipping test"); - return; - } + assumeFalse("--> noop breakers used, skipping test", noopBreakerUsed()); assertAcked(prepareCreate("cb-test", 1, Settings.builder().put(SETTING_NUMBER_OF_REPLICAS, between(0, 1)))); Client client = client(); @@ -307,10 +297,7 @@ public void clearFieldData() throws Exception { } public void testCanResetUnreasonableSettings() { - if (noopBreakerUsed()) { - logger.info("--> noop breakers used, skipping test"); - return; - } + assumeFalse("--> noop breakers used, skipping test", noopBreakerUsed()); updateClusterSettings( Settings.builder().put(HierarchyCircuitBreakerService.IN_FLIGHT_REQUESTS_CIRCUIT_BREAKER_LIMIT_SETTING.getKey(), "5b") ); @@ -333,10 +320,7 @@ public void testCanResetUnreasonableSettings() { public void testLimitsRequestSize() { ByteSizeValue inFlightRequestsLimit = ByteSizeValue.of(8, ByteSizeUnit.KB); - if (noopBreakerUsed()) { - logger.info("--> noop breakers used, skipping test"); - return; - } + assumeFalse("--> noop breakers used, skipping test", noopBreakerUsed()); internalCluster().ensureAtLeastNumDataNodes(2); @@ -418,6 +402,56 @@ public void testDynamicUseRealMemory() { updateClusterSettings(Settings.builder().putNull(totalCircuitBreakerLimitSettingKey).putNull(useRealMemoryUsageSetting)); } + public void testCircuitBreakerDuringQueryConstruction() { + assumeFalse("--> noop breakers used, skipping test", noopBreakerUsed()); + + assertAcked( + prepareCreate("cb-query-test", 1, Settings.builder().put(SETTING_NUMBER_OF_REPLICAS, between(0, 1))).setMapping( + "test_field", + "type=text" + ) + ); + + int docCount = scaledRandomIntBetween(100, 500); + List reqs = new ArrayList<>(); + for (long id = 0; id < docCount; id++) { + reqs.add(client().prepareIndex("cb-query-test").setId(Long.toString(id)).setSource("test_field", "value" + id)); + } + indexRandom(true, false, true, reqs); + + updateClusterSettings( + Settings.builder() + .put(HierarchyCircuitBreakerService.REQUEST_CIRCUIT_BREAKER_LIMIT_SETTING.getKey(), "10b") + .put(HierarchyCircuitBreakerService.REQUEST_CIRCUIT_BREAKER_OVERHEAD_SETTING.getKey(), 1.0) + ); + + BoolQueryBuilder boolQuery = new BoolQueryBuilder(); + for (int i = 0; i < 100; i++) { + boolQuery.should(new WildcardQueryBuilder("test_field", "*pattern*" + i + "*")); + } + + SearchRequestBuilder searchRequest = client().prepareSearch("cb-query-test").setQuery(boolQuery); + // This is one of the cases where a CB-trip does not translate into a 429, but instead a 400, because the query is rejected + // at construction time, before it is executed + assertFailures(searchRequest, RestStatus.BAD_REQUEST, containsString("Data too large")); + + NodesStatsResponse stats = client().admin().cluster().prepareNodesStats().setBreaker(true).get(); + long queryConstructionBreaks = 0; + for (NodeStats stat : stats.getNodes()) { + CircuitBreakerStats breakerStats = stat.getBreaker().getStats(CircuitBreaker.REQUEST); + if (breakerStats != null) { + queryConstructionBreaks += breakerStats.getTrippedCount(); + } + } + assertThat("Query construction breaker should have tripped", queryConstructionBreaks, greaterThanOrEqualTo(1L)); + + updateClusterSettings( + Settings.builder() + .putNull(HierarchyCircuitBreakerService.REQUEST_CIRCUIT_BREAKER_LIMIT_SETTING.getKey()) + .putNull(HierarchyCircuitBreakerService.REQUEST_CIRCUIT_BREAKER_OVERHEAD_SETTING.getKey()) + ); + } + private void checkLimitSize(Client client, double limitRatio) { NodesStatsResponse stats = client.admin().cluster().prepareNodesStats().setBreaker(true).setJvm(true).get(); for (NodeStats node : stats.getNodes()) { diff --git a/server/src/main/java/org/elasticsearch/index/mapper/StringFieldType.java b/server/src/main/java/org/elasticsearch/index/mapper/StringFieldType.java index 7d7b7b4b0b010..6c153ce855a7c 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/StringFieldType.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/StringFieldType.java @@ -11,6 +11,7 @@ import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.index.Term; +import org.apache.lucene.search.AutomatonQuery; import org.apache.lucene.search.FuzzyQuery; import org.apache.lucene.search.MultiTermQuery; import org.apache.lucene.search.PrefixQuery; @@ -35,10 +36,21 @@ import static org.elasticsearch.search.SearchService.ALLOW_EXPENSIVE_QUERIES; -/** Base class for {@link MappedFieldType} implementations that use the same +/** + * Base class for {@link MappedFieldType} implementations that use the same * representation for internal index terms as the external representation so * that partial matching queries such as prefix, wildcard and fuzzy queries - * can be implemented. */ + * can be implemented. + * + *

Circuit breaker accounting for automaton-based queries (prefix, wildcard, regexp, range) + * is performed here, at the point each individual Lucene query is created, rather than solely + * in {@link SearchExecutionContext#toQuery} after the full query tree is assembled. This is + * intentional: compound queries such as a {@code bool} with many wildcard clauses build each + * clause sequentially, so by the time the complete tree is available for a post-hoc walk every + * automaton has already been allocated. Accounting per-clause lets the circuit breaker trip as + * soon as cumulative memory crosses the threshold, preventing the remaining clauses from being + * constructed and avoiding a potential OOM. + */ public abstract class StringFieldType extends TermBasedFieldType { private static final Pattern WILDCARD_PATTERN = Pattern.compile("(\\\\.)|([?*]+)"); @@ -93,10 +105,14 @@ public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, bool } failIfNotIndexed(); Term prefix = new Term(name(), indexedValueForSearch(value)); + AutomatonQuery query; if (caseInsensitive) { - return method == null ? new CaseInsensitivePrefixQuery(prefix, false) : new CaseInsensitivePrefixQuery(prefix, false, method); + query = method == null ? new CaseInsensitivePrefixQuery(prefix, false) : new CaseInsensitivePrefixQuery(prefix, false, method); + } else { + query = method == null ? new PrefixQuery(prefix) : new PrefixQuery(prefix, method); } - return method == null ? new PrefixQuery(prefix) : new PrefixQuery(prefix, method); + context.addCircuitBreakerMemory(query.ramBytesUsed(), "prefix:" + name()); + return query; } public static final String normalizeWildcardPattern(String fieldname, String value, Analyzer normalizer) { @@ -160,10 +176,14 @@ protected Query wildcardQuery( } else { term = new Term(name(), indexedValueForSearch(value)); } + AutomatonQuery query; if (caseInsensitive) { - return method == null ? new CaseInsensitiveWildcardQuery(term) : new CaseInsensitiveWildcardQuery(term, false, method); + query = method == null ? new CaseInsensitiveWildcardQuery(term) : new CaseInsensitiveWildcardQuery(term, false, method); + } else { + query = method == null ? new WildcardQuery(term) : new WildcardQuery(term, Operations.DEFAULT_DETERMINIZE_WORK_LIMIT, method); } - return method == null ? new WildcardQuery(term) : new WildcardQuery(term, Operations.DEFAULT_DETERMINIZE_WORK_LIMIT, method); + context.addCircuitBreakerMemory(query.ramBytesUsed(), "wildcard:" + name()); + return query; } @Override @@ -181,7 +201,7 @@ public Query regexpQuery( ); } failIfNotIndexed(); - return method == null + AutomatonQuery query = method == null ? new RegexpQuery(new Term(name(), indexedValueForSearch(value)), syntaxFlags, matchFlags, maxDeterminizedStates) : new RegexpQuery( new Term(name(), indexedValueForSearch(value)), @@ -191,6 +211,8 @@ public Query regexpQuery( maxDeterminizedStates, method ); + context.addCircuitBreakerMemory(query.ramBytesUsed(), "regexp:" + name()); + return query; } @Override @@ -209,12 +231,14 @@ public Query rangeQuery( ); } failIfNotIndexed(); - return new TermRangeQuery( + AutomatonQuery query = new TermRangeQuery( name(), lowerTerm == null ? null : indexedValueForSearch(lowerTerm), upperTerm == null ? null : indexedValueForSearch(upperTerm), includeLower, includeUpper ); + context.addCircuitBreakerMemory(query.ramBytesUsed(), "range:" + name()); + return query; } } diff --git a/server/src/main/java/org/elasticsearch/index/query/RegexpQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/RegexpQueryBuilder.java index 1a0833693ad77..f3393d4f9490f 100644 --- a/server/src/main/java/org/elasticsearch/index/query/RegexpQueryBuilder.java +++ b/server/src/main/java/org/elasticsearch/index/query/RegexpQueryBuilder.java @@ -10,6 +10,7 @@ package org.elasticsearch.index.query; import org.apache.lucene.index.Term; +import org.apache.lucene.search.AutomatonQuery; import org.apache.lucene.search.MultiTermQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.RegexpQuery; @@ -273,7 +274,6 @@ protected Query doToQuery(SearchExecutionContext context) throws QueryShardExcep MultiTermQuery.RewriteMethod method = QueryParsers.parseRewriteMethod(rewrite, null, LoggingDeprecationHandler.INSTANCE); int matchFlagsValue = caseInsensitive ? RegExp.ASCII_CASE_INSENSITIVE : 0; - Query query = null; // For BWC we mask irrelevant bits (RegExp changed ALL from 0xffff to 0xff) // We need to preserve the DEPRECATED_COMPLEMENT for now though int deprecatedComplementFlag = syntaxFlagsValue & RegExp.DEPRECATED_COMPLEMENT; @@ -281,25 +281,22 @@ protected Query doToQuery(SearchExecutionContext context) throws QueryShardExcep MappedFieldType fieldType = context.getFieldType(fieldName); if (fieldType != null) { - query = fieldType.regexpQuery(value, sanitisedSyntaxFlag, matchFlagsValue, maxDeterminizedStates, method, context); - } - if (query == null) { - return method == null - ? new RegexpQuery( - new Term(fieldName, BytesRefs.toBytesRef(value)), - sanitisedSyntaxFlag, - matchFlagsValue, - maxDeterminizedStates - ) - : new RegexpQuery( - new Term(fieldName, BytesRefs.toBytesRef(value)), - sanitisedSyntaxFlag, - matchFlagsValue, - RegexpQuery.DEFAULT_PROVIDER, - maxDeterminizedStates, - method - ); + Query query = fieldType.regexpQuery(value, sanitisedSyntaxFlag, matchFlagsValue, maxDeterminizedStates, method, context); + if (query != null) { + return query; + } } + AutomatonQuery query = method == null + ? new RegexpQuery(new Term(fieldName, BytesRefs.toBytesRef(value)), sanitisedSyntaxFlag, matchFlagsValue, maxDeterminizedStates) + : new RegexpQuery( + new Term(fieldName, BytesRefs.toBytesRef(value)), + sanitisedSyntaxFlag, + matchFlagsValue, + RegexpQuery.DEFAULT_PROVIDER, + maxDeterminizedStates, + method + ); + context.addCircuitBreakerMemory(query.ramBytesUsed(), "regexp:" + fieldName); return query; } diff --git a/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java b/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java index f4d66a8d718df..da712d9ead109 100644 --- a/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java +++ b/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java @@ -23,6 +23,7 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.client.internal.Client; import org.elasticsearch.common.ParsingException; +import org.elasticsearch.common.breaker.CircuitBreaker; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.lucene.search.Queries; import org.elasticsearch.core.Nullable; @@ -73,6 +74,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.BooleanSupplier; @@ -112,6 +114,9 @@ public class SearchExecutionContext extends QueryRewriteContext { private final Integer requestSize; private final MapperMetrics mapperMetrics; private final ShardSearchStats shardSearchStats; + @Nullable + private final CircuitBreaker circuitBreaker; + private final AtomicLong queryConstructionMemoryUsed = new AtomicLong(0); public SearchExecutionContext( int shardId, @@ -163,11 +168,22 @@ public SearchExecutionContext( parseRuntimeMappings(runtimeMappings, mapperService, indexSettings, mappingLookup), requestSize, mapperMetrics, - shardSearchStats + shardSearchStats, + null ); } + /** + * Copy constructor that preserves the circuit breaker from the source context. + */ public SearchExecutionContext(SearchExecutionContext source) { + this(source, source.circuitBreaker); + } + + /** + * Copy constructor that overrides the circuit breaker. + */ + public SearchExecutionContext(SearchExecutionContext source, @Nullable CircuitBreaker circuitBreaker) { this( source.shardId, source.shardRequestIndex, @@ -191,7 +207,8 @@ public SearchExecutionContext(SearchExecutionContext source) { source.runtimeMappings, source.requestSize, source.mapperMetrics, - source.shardSearchStats + source.shardSearchStats, + circuitBreaker ); } @@ -218,7 +235,8 @@ private SearchExecutionContext( Map runtimeMappings, Integer requestSize, MapperMetrics mapperMetrics, - ShardSearchStats shardSearchStats + ShardSearchStats shardSearchStats, + @Nullable CircuitBreaker circuitBreaker ) { super( parserConfig, @@ -254,6 +272,7 @@ private SearchExecutionContext( this.requestSize = requestSize; this.mapperMetrics = mapperMetrics; this.shardSearchStats = shardSearchStats; + this.circuitBreaker = circuitBreaker; } private void reset() { @@ -718,4 +737,38 @@ public boolean rewriteToNamedQuery() { public ShardSearchStats stats() { return shardSearchStats; } + + /** + * Adds memory usage to the circuit breaker for query construction. + *

+ * This method tracks memory used during query construction and enforces circuit breaker limits + * to prevent excessive memory usage. The tracked memory can later be released using + * {@link #releaseQueryConstructionMemory()}. + * + * @param bytes the number of bytes to add to the circuit breaker + * @param label a descriptive label for the memory allocation, used in circuit breaker error messages + */ + public void addCircuitBreakerMemory(long bytes, String label) { + if (circuitBreaker != null) { + circuitBreaker.addEstimateBytesAndMaybeBreak(bytes, label); + queryConstructionMemoryUsed.addAndGet(bytes); + } + } + + /** + * Get total query construction memory used. + */ + public long getQueryConstructionMemoryUsed() { + return queryConstructionMemoryUsed.get(); + } + + /** + * Release all accumulated query construction memory back to the circuit breaker. + */ + public void releaseQueryConstructionMemory() { + long memoryToRelease = queryConstructionMemoryUsed.getAndSet(0); + if (memoryToRelease > 0 && circuitBreaker != null) { + circuitBreaker.addWithoutBreaking(-memoryToRelease); + } + } } diff --git a/server/src/main/java/org/elasticsearch/search/DefaultSearchContext.java b/server/src/main/java/org/elasticsearch/search/DefaultSearchContext.java index f1d14691f0715..0d211f2bb6498 100644 --- a/server/src/main/java/org/elasticsearch/search/DefaultSearchContext.java +++ b/server/src/main/java/org/elasticsearch/search/DefaultSearchContext.java @@ -172,7 +172,8 @@ final class DefaultSearchContext extends SearchContext { SearchService.ResultsType resultsType, boolean enableQueryPhaseParallelCollection, int minimumDocsPerSlice, - long memoryAccountingBufferSize + long memoryAccountingBufferSize, + @Nullable CircuitBreaker circuitBreaker ) throws IOException { this.readerContext = readerContext; this.request = request; @@ -216,7 +217,7 @@ final class DefaultSearchContext extends SearchContext { closeFuture.addListener(ActionListener.releasing(Releasables.wrap(engineSearcher, searcher))); this.relativeTimeSupplier = relativeTimeSupplier; this.timeout = timeout; - searchExecutionContext = indexService.newSearchExecutionContext( + SearchExecutionContext baseContext = indexService.newSearchExecutionContext( request.shardId().id(), request.shardRequestIndex(), searcher, @@ -226,6 +227,7 @@ final class DefaultSearchContext extends SearchContext { request.source() == null ? null : request.source().size(), indexShard.shardSearchStats() ); + searchExecutionContext = circuitBreaker != null ? new SearchExecutionContext(baseContext, circuitBreaker) : baseContext; queryBoost = request.indexBoost(); this.lowLevelCancellation = lowLevelCancellation; success = true; diff --git a/server/src/main/java/org/elasticsearch/search/SearchService.java b/server/src/main/java/org/elasticsearch/search/SearchService.java index 980da54ea9643..1e21a39baff53 100644 --- a/server/src/main/java/org/elasticsearch/search/SearchService.java +++ b/server/src/main/java/org/elasticsearch/search/SearchService.java @@ -405,7 +405,7 @@ public SearchService( this.scriptService = scriptService; this.bigArrays = bigArrays; this.fetchPhase = fetchPhase; - circuitBreaker = circuitBreakerService.getBreaker(CircuitBreaker.REQUEST); + this.circuitBreaker = circuitBreakerService.getBreaker(CircuitBreaker.REQUEST); this.multiBucketConsumerService = new MultiBucketConsumerService(clusterService, settings, circuitBreaker); this.executorSelector = executorSelector; this.tracer = tracer; @@ -1463,6 +1463,10 @@ protected SearchContext createContext( checkCancelled(task); final DefaultSearchContext context = createSearchContext(readerContext, request, defaultSearchTimeout, resultsType); resultsType.addResultsObject(context); + + // Release the memory used for query construction once the search context is closed. + context.addReleasable(context.getSearchExecutionContext()::releaseQueryConstructionMemory); + try { if (request.scroll() != null) { context.scrollContext().scroll = request.scroll(); @@ -1496,6 +1500,7 @@ public SearchContext createSearchContext(ShardSearchRequest request, TimeValue t // Use ResultsType.QUERY so that the created search context can execute queries correctly. DefaultSearchContext searchContext = createSearchContext(readerContext, request, timeout, ResultsType.QUERY); searchContext.addReleasable(readerContext.markAsUsed(0L)); + searchContext.addReleasable(searchContext.getSearchExecutionContext()::releaseQueryConstructionMemory); return searchContext; } } @@ -1527,18 +1532,24 @@ private DefaultSearchContext createSearchContext( resultsType, enableQueryPhaseParallelCollection, minimumDocsPerSlice, - memoryAccountingBufferSize + memoryAccountingBufferSize, + circuitBreaker ); // we clone the query shard context here just for rewriting otherwise we // might end up with incorrect state since we are using now() or script services // during rewrite and normalized / evaluate templates etc. SearchExecutionContext context = new SearchExecutionContext(searchContext.getSearchExecutionContext()); + Rewriteable.rewrite(request.getRewriteable(), context, true); + assert context.getQueryConstructionMemoryUsed() == 0 + : "rewrite phase should not build queries; found " + context.getQueryConstructionMemoryUsed() + " bytes tracked"; + if (context.getTimeRangeFilterFromMillis() != null) { // range queries may get rewritten to match_all or a range with open bounds. Rewriting in that case is the only place // where we parse the date and set it to the context. We need to propagate it back from the clone into the original context searchContext.getSearchExecutionContext().setTimeRangeFilterFromMillis(context.getTimeRangeFilterFromMillis()); } + assert searchContext.getSearchExecutionContext().isCacheable(); success = true; } finally { @@ -2391,4 +2402,5 @@ public AggregationReduceContext forFinalReduction() { } }; } + } diff --git a/server/src/test/java/org/elasticsearch/index/query/PrefixQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/PrefixQueryBuilderTests.java index 918815f2a4f77..458eb60e5039d 100644 --- a/server/src/test/java/org/elasticsearch/index/query/PrefixQueryBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/PrefixQueryBuilderTests.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.stream.IntStream; import static org.elasticsearch.index.query.QueryBuilders.prefixQuery; import static org.hamcrest.Matchers.equalTo; @@ -89,11 +90,16 @@ public void testIllegalArguments() { public void testBlendedRewriteMethod() throws IOException { String rewrite = "top_terms_blended_freqs_10"; - Query parsedQuery = parseQuery(prefixQuery(TEXT_FIELD_NAME, "val").rewrite(rewrite)).toQuery(createSearchExecutionContext()); - assertThat(parsedQuery, instanceOf(PrefixQuery.class)); - PrefixQuery prefixQuery = (PrefixQuery) parsedQuery; - assertThat(prefixQuery.getPrefix(), equalTo(new Term(TEXT_FIELD_NAME, "val"))); - assertThat(prefixQuery.getRewriteMethod(), instanceOf(MultiTermQuery.TopTermsBlendedFreqScoringRewrite.class)); + SearchExecutionContext context = new SearchExecutionContext(createSearchExecutionContext(), createCircuitBreakerService()); + try { + Query parsedQuery = parseQuery(prefixQuery(TEXT_FIELD_NAME, "val").rewrite(rewrite)).toQuery(context); + assertThat(parsedQuery, instanceOf(PrefixQuery.class)); + PrefixQuery prefixQuery = (PrefixQuery) parsedQuery; + assertThat(prefixQuery.getPrefix(), equalTo(new Term(TEXT_FIELD_NAME, "val"))); + assertThat(prefixQuery.getRewriteMethod(), instanceOf(MultiTermQuery.TopTermsBlendedFreqScoringRewrite.class)); + } finally { + context.releaseQueryConstructionMemory(); + } } public void testFromJson() throws IOException { @@ -210,4 +216,21 @@ public void testCoordinatorTierRewriteToMatchNone() throws IOException { assertThat(rewritten, CoreMatchers.instanceOf(MatchNoneQueryBuilder.class)); } + public void testPrefixQueryCircuitBreakerAccounting() throws IOException { + assertCircuitBreakerAccountsForQuery(new PrefixQueryBuilder(TEXT_FIELD_NAME, "test")); + } + + public void testPrefixCircuitBreakerTripsWithLowLimit() { + assertCircuitBreakerTripsOnQueryConstruction("500kb", () -> { + BoolQueryBuilder boolQuery = new BoolQueryBuilder(); + IntStream.range(0, 100).forEach(i -> { + PrefixQueryBuilder prefixQuery = new PrefixQueryBuilder(TEXT_FIELD_NAME, "prefix" + i); + if (randomBoolean()) { + prefixQuery.caseInsensitive(true); + } + boolQuery.should(prefixQuery); + }); + return boolQuery; + }); + } } diff --git a/server/src/test/java/org/elasticsearch/index/query/QueryStringQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/QueryStringQueryBuilderTests.java index b39cb8738c4be..7f6474d4fdc51 100644 --- a/server/src/test/java/org/elasticsearch/index/query/QueryStringQueryBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/QueryStringQueryBuilderTests.java @@ -66,6 +66,8 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.StringJoiner; +import java.util.stream.IntStream; import static org.elasticsearch.index.query.AbstractQueryBuilder.parseTopLevelQuery; import static org.elasticsearch.index.query.QueryBuilders.queryStringQuery; @@ -1435,4 +1437,20 @@ public void testWhitespaceKeywordQueries() throws IOException { Query q = b.doToQuery(createSearchExecutionContext()); assertEquals(new TermQuery(new Term("ww_keyword", "query with spaces")), q); } + + public void testQueryStringCircuitBreakerTripsWithManyWildcards() { + assertCircuitBreakerTripsOnQueryConstruction("1mb", () -> { + StringJoiner joiner = new StringJoiner(" OR "); + IntStream.range(0, 100).forEach(i -> joiner.add("*a*b*c*d*e*f*g*h*" + i + "*")); + return queryStringQuery(joiner.toString()).defaultField(TEXT_FIELD_NAME); + }); + } + + public void testQueryStringCircuitBreakerTripsWithManyRegexps() { + assertCircuitBreakerTripsOnQueryConstruction("500kb", () -> { + StringJoiner joiner = new StringJoiner(" OR "); + IntStream.range(0, 50).forEach(i -> joiner.add("/(pattern" + i + "|alternate" + i + "|option" + i + ").*/")); + return queryStringQuery(joiner.toString()).defaultField(TEXT_FIELD_NAME); + }); + } } diff --git a/server/src/test/java/org/elasticsearch/index/query/RangeQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/RangeQueryBuilderTests.java index a56fd36ceb0d2..66f11faacf831 100644 --- a/server/src/test/java/org/elasticsearch/index/query/RangeQueryBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/RangeQueryBuilderTests.java @@ -678,4 +678,15 @@ public void testCacheability() throws IOException { assertNotNull(rewriteQuery.toQuery(context)); assertFalse("query should not be cacheable: " + queryBuilder.toString(), context.isCacheable()); } + + public void testRangeQueryCircuitBreakerAccountingTextFields() throws IOException { + assertCircuitBreakerAccountsForQuery(new RangeQueryBuilder(TEXT_FIELD_NAME).gte("aaa").lte("zzz")); + } + + public void testRangeQueryCircuitBreakerTripsOnLargeTextRange() { + assertCircuitBreakerTripsOnQueryConstruction( + "1kb", + () -> new RangeQueryBuilder(TEXT_FIELD_NAME).gte("a").lte("zzzzzzzzzzzzzzzzzzzz") + ); + } } diff --git a/server/src/test/java/org/elasticsearch/index/query/RegexpQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/RegexpQueryBuilderTests.java index 62073ef7e451c..606941f154ded 100644 --- a/server/src/test/java/org/elasticsearch/index/query/RegexpQueryBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/RegexpQueryBuilderTests.java @@ -20,6 +20,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.IntStream; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; @@ -145,4 +146,21 @@ public void testParseFailsWithMultipleFields() throws IOException { e = expectThrows(ParsingException.class, () -> parseQuery(shortJson)); assertEquals("[regexp] query doesn't support multiple fields, found [user1] and [user2]", e.getMessage()); } + + public void testRegexpQueryCircuitBreakerAccounting() throws IOException { + assertCircuitBreakerAccountsForQuery(new RegexpQueryBuilder(TEXT_FIELD_NAME, ".*test.*pattern.*")); + } + + public void testRegexpCircuitBreakerTripsWithLowLimit() { + assertCircuitBreakerTripsOnQueryConstruction("500kb", () -> { + BoolQueryBuilder boolQuery = new BoolQueryBuilder(); + IntStream.range(0, 50) + .forEach( + i -> boolQuery.should( + new RegexpQueryBuilder(TEXT_FIELD_NAME, "(pattern" + i + "|alternate" + i + "|option" + i + ").*") + ) + ); + return boolQuery; + }); + } } diff --git a/server/src/test/java/org/elasticsearch/index/query/WildcardQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/WildcardQueryBuilderTests.java index 302b49e949564..c8bae9f134a91 100644 --- a/server/src/test/java/org/elasticsearch/index/query/WildcardQueryBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/WildcardQueryBuilderTests.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.stream.IntStream; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; @@ -201,4 +202,17 @@ public void testCoordinatorTierRewriteToMatchNone() throws IOException { QueryBuilder rewritten = query.rewrite(coordinatorRewriteContext); assertThat(rewritten, CoreMatchers.instanceOf(MatchNoneQueryBuilder.class)); } + + public void testWildcardQueryCircuitBreakerAccounting() throws IOException { + assertCircuitBreakerAccountsForQuery(new WildcardQueryBuilder(TEXT_FIELD_NAME, "test*pattern*with*wildcards*")); + } + + public void testCircuitBreakerTripsWithLowLimit() { + assertCircuitBreakerTripsOnQueryConstruction("1mb", () -> { + BoolQueryBuilder boolQuery = new BoolQueryBuilder(); + IntStream.range(0, 100) + .forEach(i -> boolQuery.should(new WildcardQueryBuilder(TEXT_FIELD_NAME, "*a*b*c*d*e*f*g*h*i*j*k*l*m*n*o*p*" + i + "*"))); + return boolQuery; + }); + } } diff --git a/server/src/test/java/org/elasticsearch/search/DefaultSearchContextTests.java b/server/src/test/java/org/elasticsearch/search/DefaultSearchContextTests.java index 6084c843e33f7..35ea1e676dc76 100644 --- a/server/src/test/java/org/elasticsearch/search/DefaultSearchContextTests.java +++ b/server/src/test/java/org/elasticsearch/search/DefaultSearchContextTests.java @@ -201,7 +201,8 @@ protected Engine.Searcher acquireSearcherInternal(String source) { randomFrom(SearchService.ResultsType.values()), randomBoolean(), randomInt(), - MEMORY_ACCOUNTING_BUFFER_SIZE + MEMORY_ACCOUNTING_BUFFER_SIZE, + null ); contextWithoutScroll.from(300); contextWithoutScroll.close(); @@ -244,8 +245,8 @@ protected Engine.Searcher acquireSearcherInternal(String source) { randomFrom(SearchService.ResultsType.values()), randomBoolean(), randomInt(), - MEMORY_ACCOUNTING_BUFFER_SIZE - + MEMORY_ACCOUNTING_BUFFER_SIZE, + null ) ) { context1.from(300); @@ -328,7 +329,8 @@ public ScrollContext scrollContext() { randomFrom(SearchService.ResultsType.values()), randomBoolean(), randomInt(), - MEMORY_ACCOUNTING_BUFFER_SIZE + MEMORY_ACCOUNTING_BUFFER_SIZE, + null ) ) { @@ -371,7 +373,8 @@ public ScrollContext scrollContext() { randomFrom(SearchService.ResultsType.values()), randomBoolean(), randomInt(), - MEMORY_ACCOUNTING_BUFFER_SIZE + MEMORY_ACCOUNTING_BUFFER_SIZE, + null ) ) { context3.sliceBuilder(null).parsedQuery(parsedQuery).preProcess(); @@ -403,7 +406,8 @@ public ScrollContext scrollContext() { randomFrom(SearchService.ResultsType.values()), randomBoolean(), randomInt(), - MEMORY_ACCOUNTING_BUFFER_SIZE + MEMORY_ACCOUNTING_BUFFER_SIZE, + null ) ) { context4.sliceBuilder(new SliceBuilder(1, 2)).parsedQuery(parsedQuery).preProcess(); @@ -475,7 +479,8 @@ protected Engine.Searcher acquireSearcherInternal(String source) { randomFrom(SearchService.ResultsType.values()), randomBoolean(), randomInt(), - MEMORY_ACCOUNTING_BUFFER_SIZE + MEMORY_ACCOUNTING_BUFFER_SIZE, + null ); assertThat(context.searcher().hasCancellations(), is(false)); @@ -1105,7 +1110,8 @@ protected Engine.Searcher acquireSearcherInternal(String source) { randomFrom(SearchService.ResultsType.values()), randomBoolean(), randomInt(), - MEMORY_ACCOUNTING_BUFFER_SIZE + MEMORY_ACCOUNTING_BUFFER_SIZE, + null ); } } diff --git a/server/src/test/java/org/elasticsearch/search/SearchServiceTests.java b/server/src/test/java/org/elasticsearch/search/SearchServiceTests.java index 6bc5e9e4b63bb..75e4cb9fdfb5b 100644 --- a/server/src/test/java/org/elasticsearch/search/SearchServiceTests.java +++ b/server/src/test/java/org/elasticsearch/search/SearchServiceTests.java @@ -20,8 +20,11 @@ import org.elasticsearch.action.OriginalIndices; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.cluster.metadata.IndexMetadata; +import org.elasticsearch.common.breaker.CircuitBreaker; +import org.elasticsearch.common.breaker.CircuitBreakingException; import org.elasticsearch.common.component.Lifecycle; import org.elasticsearch.common.regex.Regex; +import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.BigArrays; import org.elasticsearch.index.IndexMode; @@ -42,15 +45,19 @@ import org.elasticsearch.index.mapper.MetadataFieldMapper; import org.elasticsearch.index.mapper.ObjectMapper; import org.elasticsearch.index.mapper.RootObjectMapper; +import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.MatchAllQueryBuilder; import org.elasticsearch.index.query.MatchNoneQueryBuilder; import org.elasticsearch.index.query.QueryRewriteContext; import org.elasticsearch.index.query.RangeQueryBuilder; import org.elasticsearch.index.query.SearchExecutionContext; import org.elasticsearch.index.query.SearchExecutionContextHelper; +import org.elasticsearch.index.query.WildcardQueryBuilder; import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShardTestCase; import org.elasticsearch.index.shard.ShardId; +import org.elasticsearch.indices.breaker.CircuitBreakerMetrics; +import org.elasticsearch.indices.breaker.HierarchyCircuitBreakerService; import org.elasticsearch.script.ScriptCompiler; import org.elasticsearch.search.aggregations.support.ValuesSourceType; import org.elasticsearch.search.builder.SearchSourceBuilder; @@ -389,6 +396,106 @@ public void testIsExecutorQueuedBeyondPrewarmingFactor() throws InterruptedExcep } } + public void testBuildQueryWithCircuitBreakerAccountsMemory() throws IOException { + IndexShard indexShard = newShard(true); + try { + recoverShardFromStore(indexShard); + try (Engine.Searcher searcher = indexShard.acquireSearcher("test")) { + CircuitBreaker cb = createQueryConstructionBreaker("100mb"); + SearchExecutionContext context = new SearchExecutionContext( + createSearchExecutionContext((mappedFieldType, fieldDataContext) -> null, searcher), + cb + ); + + try { + long cbBefore = cb.getUsed(); + assertEquals("Freshly created breaker must start at zero", 0L, cbBefore); + + WildcardQueryBuilder queryBuilder = new WildcardQueryBuilder("field", "*test*pattern*"); + assertNotNull(queryBuilder.toQuery(context)); + + long cbAfter = cb.getUsed(); + long tracked = context.getQueryConstructionMemoryUsed(); + + assertTrue("Circuit breaker should have accounted memory", cbAfter > cbBefore); + assertTrue("Context should have tracked memory", tracked > 0); + assertEquals("CB delta must match tracked memory", cbAfter - cbBefore, tracked); + } finally { + context.releaseQueryConstructionMemory(); + } + } + } finally { + closeShards(indexShard); + } + } + + public void testBuildQueryWithCircuitBreakerTripsOnLimitExceeded() throws IOException { + IndexShard indexShard = newShard(true); + try { + recoverShardFromStore(indexShard); + try (Engine.Searcher searcher = indexShard.acquireSearcher("test")) { + CircuitBreaker cb = createQueryConstructionBreaker("1kb"); + SearchExecutionContext context = new SearchExecutionContext( + createSearchExecutionContext((mappedFieldType, fieldDataContext) -> null, searcher), + cb + ); + + try { + BoolQueryBuilder boolQuery = new BoolQueryBuilder(); + for (int i = 0; i < 50; i++) { + boolQuery.should(new WildcardQueryBuilder("field", "*a*b*c*" + i + "*")); + } + + expectThrows(CircuitBreakingException.class, () -> boolQuery.toQuery(context)); + } finally { + context.releaseQueryConstructionMemory(); + } + } + } finally { + closeShards(indexShard); + } + } + + public void testQueryConstructionMemoryReleasedOnContextClose() throws IOException { + IndexShard indexShard = newShard(true); + try { + recoverShardFromStore(indexShard); + try (Engine.Searcher searcher = indexShard.acquireSearcher("test")) { + CircuitBreaker cb = createQueryConstructionBreaker("100mb"); + SearchExecutionContext context = new SearchExecutionContext( + createSearchExecutionContext((mappedFieldType, fieldDataContext) -> null, searcher), + cb + ); + + for (int i = 0; i < 3; i++) { + new WildcardQueryBuilder("field", "*test" + i + "*").toQuery(context); + } + + long cbAfterBuild = cb.getUsed(); + long tracked = context.getQueryConstructionMemoryUsed(); + assertTrue("Memory should be accounted before release", cbAfterBuild > 0); + assertEquals("Tracked memory should match CB", cbAfterBuild, tracked); + + context.releaseQueryConstructionMemory(); + + assertEquals("CB must be fully released", 0L, cb.getUsed()); + assertEquals("Tracked memory must be zeroed", 0L, context.getQueryConstructionMemoryUsed()); + } + } finally { + closeShards(indexShard); + } + } + + private CircuitBreaker createQueryConstructionBreaker(String limit) { + Settings settings = Settings.builder() + .put(HierarchyCircuitBreakerService.REQUEST_CIRCUIT_BREAKER_LIMIT_SETTING.getKey(), limit) + .put(HierarchyCircuitBreakerService.USE_REAL_MEMORY_USAGE_SETTING.getKey(), false) + .build(); + ClusterSettings clusterSettings = new ClusterSettings(settings, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + return new HierarchyCircuitBreakerService(CircuitBreakerMetrics.NOOP, settings, Collections.emptyList(), clusterSettings) + .getBreaker(CircuitBreaker.REQUEST); + } + private SearchService.CanMatchContext doTestCanMatch( SearchRequest searchRequest, SortField sortField, diff --git a/test/framework/src/main/java/org/elasticsearch/test/AbstractBuilderTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/AbstractBuilderTestCase.java index e9beb049b4d85..ef0533226fdeb 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/AbstractBuilderTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/AbstractBuilderTestCase.java @@ -13,6 +13,8 @@ import com.carrotsearch.randomizedtesting.SeedUtils; import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.Query; +import org.apache.lucene.util.Accountable; import org.elasticsearch.TransportVersion; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.MockResolvedIndices; @@ -29,6 +31,8 @@ import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; +import org.elasticsearch.common.breaker.CircuitBreaker; +import org.elasticsearch.common.breaker.CircuitBreakingException; import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.regex.Regex; @@ -55,6 +59,7 @@ import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.query.CoordinatorRewriteContext; import org.elasticsearch.index.query.DataRewriteContext; +import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryRewriteContext; import org.elasticsearch.index.query.SearchExecutionContext; import org.elasticsearch.index.query.SearchExecutionContextHelper; @@ -64,6 +69,9 @@ import org.elasticsearch.indices.DateFieldRangeInfo; import org.elasticsearch.indices.IndicesModule; import org.elasticsearch.indices.analysis.AnalysisModule; +import org.elasticsearch.indices.breaker.CircuitBreakerMetrics; +import org.elasticsearch.indices.breaker.CircuitBreakerService; +import org.elasticsearch.indices.breaker.HierarchyCircuitBreakerService; import org.elasticsearch.indices.breaker.NoneCircuitBreakerService; import org.elasticsearch.indices.fielddata.cache.IndicesFieldDataCache; import org.elasticsearch.node.InternalSettingsPreparer; @@ -109,12 +117,14 @@ import java.util.concurrent.ExecutionException; import java.util.function.Function; import java.util.function.Predicate; +import java.util.function.Supplier; import java.util.stream.Stream; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonList; import static java.util.stream.Collectors.toList; +import static org.hamcrest.Matchers.containsString; public abstract class AbstractBuilderTestCase extends ESTestCase { @@ -422,6 +432,86 @@ public MultiTermVectorsResponse get() throws InterruptedException, ExecutionExce } + protected static CircuitBreaker createCircuitBreakerService(String limit) { + Settings settings = Settings.builder() + .put("indices.breaker.request.limit", limit) + .put("indices.breaker.request.overhead", "1.0") + .build(); + + ClusterSettings clusterSettings = new ClusterSettings(settings, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + CircuitBreakerService service = new HierarchyCircuitBreakerService( + CircuitBreakerMetrics.NOOP, + settings, + Collections.emptyList(), + clusterSettings + ); + + return service.getBreaker(CircuitBreaker.REQUEST); + } + + /** + * Creates a circuit breaker for testing query construction with default limit (10% of heap). + * + * @return a configured CircuitBreaker instance + */ + protected static CircuitBreaker createCircuitBreakerService() { + return createCircuitBreakerService("10%"); + } + + /** + * Override this method to provide a custom CircuitBreakerService for tests. + * By default, returns NoneCircuitBreakerService for backwards compatibility. + * + * @param nodeSettings the node settings + * @param clusterSettings the cluster settings + * @return the CircuitBreakerService to use in tests + */ + protected CircuitBreakerService createCircuitBreakerService(Settings nodeSettings, ClusterSettings clusterSettings) { + return new NoneCircuitBreakerService(); + } + + /** + * Asserts that building the supplied query trips the circuit breaker with a "Data too large" message. + */ + protected static void assertCircuitBreakerTripsOnQueryConstruction(String breakerLimit, Supplier querySupplier) { + SearchExecutionContext context = new SearchExecutionContext( + createSearchExecutionContext(), + createCircuitBreakerService(breakerLimit) + ); + + try { + QueryBuilder query = querySupplier.get(); + CircuitBreakingException exception = expectThrows(CircuitBreakingException.class, () -> query.toQuery(context)); + assertThat(exception.getMessage(), containsString("Data too large")); + } finally { + context.releaseQueryConstructionMemory(); + } + } + + /** + * Asserts that the circuit breaker correctly accounts for the memory used by the given query. + */ + protected static void assertCircuitBreakerAccountsForQuery(QueryBuilder queryBuilder) throws IOException { + CircuitBreaker cb = createCircuitBreakerService(); + SearchExecutionContext context = new SearchExecutionContext(createSearchExecutionContext(), cb); + + try { + long before = cb.getUsed(); + Query query = queryBuilder.toQuery(context); + long after = cb.getUsed(); + + if (query instanceof Accountable accountable) { + long queryMemory = accountable.ramBytesUsed(); + if (queryMemory > 0) { + assertTrue("Circuit breaker should account for query memory", after >= before); + assertEquals("Circuit breaker delta should equal query ramBytesUsed", queryMemory, after - before); + } + } + } finally { + context.releaseQueryConstructionMemory(); + } + } + private static class ServiceHolder implements Closeable { private final IndexFieldDataService indexFieldDataService; private final SearchModule searchModule; @@ -436,6 +526,7 @@ private static class ServiceHolder implements Closeable { private final Client client; private final long nowInMillis; private final IndexMetadata indexMetadata; + private final CircuitBreakerService circuitBreakerService; ServiceHolder( Settings nodeSettings, @@ -452,13 +543,16 @@ private static class ServiceHolder implements Closeable { PluginsService pluginsService; pluginsService = new MockPluginsService(nodeSettings, env, plugins); + ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); ClusterService clusterService = new ClusterService( Settings.EMPTY, - new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS), + clusterSettings, new DeterministicTaskQueue().getThreadPool(), null ); + this.circuitBreakerService = testCase.createCircuitBreakerService(nodeSettings, clusterSettings); + client = (Client) Proxy.newProxyInstance( Client.class.getClassLoader(), new Class[] { Client.class }, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeSearchContext.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeSearchContext.java index db9eec83efe76..2aa43cccd046c 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeSearchContext.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeSearchContext.java @@ -58,6 +58,7 @@ public SourceProvider createSourceProvider(SourceFilter sourceFilter) { return new ReinitializingSourceProvider(super::createSourceProvider); } }; + searchContext.addReleasable(searchExecutionContext::releaseQueryConstructionMemory); return new DefaultShardContext(index, this, searchExecutionContext, searchContext.request().getAliasFilter()); } From ec13be2d7d6d52ee4eff22508d6fe2d05e5611bf Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Tue, 3 Mar 2026 13:05:22 +0200 Subject: [PATCH 057/137] ESQL: Fix datasource test failures on Windows and FIPS (#143417) Datasource tests fail on Windows CI and FIPS CI builds due to two independent issues introduced with the external sources feature. **Windows:** `StoragePath.of()` cannot parse `file://` URIs with Windows drive letters. A path like `file://C:\bk\path\file.txt` causes the colon after the drive letter `C` to be misinterpreted as a port separator, resulting in `NumberFormatException`. Both the production code (`LocalStorageProvider.toStoragePath()`) and the tests construct file URIs via manual string concatenation instead of using the existing `StoragePath.fileUri()` helper that normalizes Windows paths correctly. **FIPS:** `ExternalDistributedSpecIT` starts a test cluster with `xpack.security.enabled=false`, but FIPS mode requires security to be enabled. The Elasticsearch process dies during startup before any test method runs. Since the test relies on plain HTTP S3 fixtures that are inherently incompatible with FIPS, the test is now skipped in FIPS mode. Developed using AI-assisted tooling --- docs/changelog/143417.yaml | 5 +++ .../http/local/LocalStorageProvider.java | 2 +- .../http/local/LocalStorageProviderTests.java | 20 +++++----- .../multi_node/ExternalDistributedSpecIT.java | 14 ++++++- .../esql/datasources/spi/StoragePath.java | 23 +++++++++-- .../datasources/spi/StoragePathTests.java | 40 +++++++++++++++++++ 6 files changed, 88 insertions(+), 16 deletions(-) create mode 100644 docs/changelog/143417.yaml diff --git a/docs/changelog/143417.yaml b/docs/changelog/143417.yaml new file mode 100644 index 0000000000000..392c541a8c33f --- /dev/null +++ b/docs/changelog/143417.yaml @@ -0,0 +1,5 @@ +area: ES|QL +issues: [] +pr: 143417 +summary: Fix datasource test failures on Windows and FIPS +type: bug diff --git a/x-pack/plugin/esql-datasource-http/src/main/java/org/elasticsearch/xpack/esql/datasource/http/local/LocalStorageProvider.java b/x-pack/plugin/esql-datasource-http/src/main/java/org/elasticsearch/xpack/esql/datasource/http/local/LocalStorageProvider.java index 0c2791f9a886c..9df0dc4db4ea8 100644 --- a/x-pack/plugin/esql-datasource-http/src/main/java/org/elasticsearch/xpack/esql/datasource/http/local/LocalStorageProvider.java +++ b/x-pack/plugin/esql-datasource-http/src/main/java/org/elasticsearch/xpack/esql/datasource/http/local/LocalStorageProvider.java @@ -137,7 +137,7 @@ public String toString() { } private static StoragePath toStoragePath(Path filePath) { - return StoragePath.of(FILE_SCHEME_PREFIX + filePath.toAbsolutePath()); + return StoragePath.of(StoragePath.fileUri(filePath)); } /** diff --git a/x-pack/plugin/esql-datasource-http/src/test/java/org/elasticsearch/xpack/esql/datasource/http/local/LocalStorageProviderTests.java b/x-pack/plugin/esql-datasource-http/src/test/java/org/elasticsearch/xpack/esql/datasource/http/local/LocalStorageProviderTests.java index ae1accf2bc880..8a6ed70f1bb86 100644 --- a/x-pack/plugin/esql-datasource-http/src/test/java/org/elasticsearch/xpack/esql/datasource/http/local/LocalStorageProviderTests.java +++ b/x-pack/plugin/esql-datasource-http/src/test/java/org/elasticsearch/xpack/esql/datasource/http/local/LocalStorageProviderTests.java @@ -36,7 +36,7 @@ public void testReadFullFile() throws IOException { // Create storage provider and object LocalStorageProvider provider = new LocalStorageProvider(); - StoragePath path = StoragePath.of("file://" + tempFile.toAbsolutePath()); + StoragePath path = StoragePath.of(StoragePath.fileUri(tempFile)); StorageObject object = provider.newObject(path); // Read the full file @@ -59,7 +59,7 @@ public void testReadRangeFromFile() throws IOException { // Create storage provider and object LocalStorageProvider provider = new LocalStorageProvider(); - StoragePath path = StoragePath.of("file://" + tempFile.toAbsolutePath()); + StoragePath path = StoragePath.of(StoragePath.fileUri(tempFile)); StorageObject object = provider.newObject(path); // Read a range (bytes 5-9, which should be "56789") @@ -79,7 +79,7 @@ public void testFileMetadata() throws IOException { // Create storage provider and object LocalStorageProvider provider = new LocalStorageProvider(); - StoragePath path = StoragePath.of("file://" + tempFile.toAbsolutePath()); + StoragePath path = StoragePath.of(StoragePath.fileUri(tempFile)); StorageObject object = provider.newObject(path); // Check metadata @@ -98,7 +98,7 @@ public void testListDirectory() throws IOException { // Create storage provider LocalStorageProvider provider = new LocalStorageProvider(); - StoragePath dirPath = StoragePath.of("file://" + tempDir.toAbsolutePath()); + StoragePath dirPath = StoragePath.of(StoragePath.fileUri(tempDir)); // List directory List entries = new ArrayList<>(); @@ -123,7 +123,7 @@ public void testFileNotFound() throws IOException { Path nonExistentFile = tempDir.resolve("nonexistent_file.txt"); LocalStorageProvider provider = new LocalStorageProvider(); - StoragePath path = StoragePath.of("file://" + nonExistentFile.toAbsolutePath()); + StoragePath path = StoragePath.of(StoragePath.fileUri(nonExistentFile)); StorageObject object = provider.newObject(path); assertFalse(object.exists()); @@ -154,7 +154,7 @@ public void testListDirectoryNonRecursive() throws IOException { Files.createFile(sub.resolve("c.parquet")); LocalStorageProvider provider = new LocalStorageProvider(); - StoragePath prefix = StoragePath.of("file://" + tempDir.toAbsolutePath()); + StoragePath prefix = StoragePath.of(StoragePath.fileUri(tempDir)); List names = collectObjectNames(provider.listObjects(prefix, false)); assertEquals(List.of("a.parquet", "b.parquet"), sorted(names)); @@ -169,7 +169,7 @@ public void testListDirectoryRecursive() throws IOException { Files.createFile(deep.resolve("d.parquet")); LocalStorageProvider provider = new LocalStorageProvider(); - StoragePath prefix = StoragePath.of("file://" + tempDir.toAbsolutePath()); + StoragePath prefix = StoragePath.of(StoragePath.fileUri(tempDir)); List names = collectObjectNames(provider.listObjects(prefix, true)); assertEquals(List.of("a.parquet", "c.parquet", "d.parquet"), sorted(names)); @@ -183,7 +183,7 @@ public void testListDirectoryRecursiveMultipleSubdirs() throws IOException { } LocalStorageProvider provider = new LocalStorageProvider(); - StoragePath prefix = StoragePath.of("file://" + tempDir.toAbsolutePath()); + StoragePath prefix = StoragePath.of(StoragePath.fileUri(tempDir)); List entries = collectAll(provider.listObjects(prefix, true)); assertEquals(3, entries.size()); @@ -193,7 +193,7 @@ public void testListEmptyDirectoryReturnsNothing() throws IOException { Path tempDir = createTempDir(); LocalStorageProvider provider = new LocalStorageProvider(); - StoragePath prefix = StoragePath.of("file://" + tempDir.toAbsolutePath()); + StoragePath prefix = StoragePath.of(StoragePath.fileUri(tempDir)); List entries = collectAll(provider.listObjects(prefix, true)); assertEquals(0, entries.size()); @@ -225,7 +225,7 @@ public void testListDirectoryRecursiveRandomTree() throws IOException { } LocalStorageProvider provider = new LocalStorageProvider(); - StoragePath prefix = StoragePath.of("file://" + tempDir.toAbsolutePath()); + StoragePath prefix = StoragePath.of(StoragePath.fileUri(tempDir)); List entries = collectAll(provider.listObjects(prefix, true)); assertEquals(totalFiles, entries.size()); diff --git a/x-pack/plugin/esql/qa/server/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/multi_node/ExternalDistributedSpecIT.java b/x-pack/plugin/esql/qa/server/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/multi_node/ExternalDistributedSpecIT.java index bb97c70d49755..6cb817e7db689 100644 --- a/x-pack/plugin/esql/qa/server/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/multi_node/ExternalDistributedSpecIT.java +++ b/x-pack/plugin/esql/qa/server/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/multi_node/ExternalDistributedSpecIT.java @@ -20,6 +20,8 @@ import org.elasticsearch.xpack.esql.plugin.QueryPragmas; import org.elasticsearch.xpack.esql.qa.rest.AbstractExternalSourceSpecTestCase; import org.junit.ClassRule; +import org.junit.rules.RuleChain; +import org.junit.rules.TestRule; import java.io.IOException; import java.util.ArrayList; @@ -45,8 +47,18 @@ public boolean reject(Thread t) { private static final List DISTRIBUTION_MODES = List.of("coordinator_only", "round_robin", "adaptive"); + private static ElasticsearchCluster clusterInstance = ExternalDistributedClusters.testCluster(() -> s3Fixture.getAddress()); + @ClassRule - public static ElasticsearchCluster cluster = ExternalDistributedClusters.testCluster(() -> s3Fixture.getAddress()); + public static TestRule ruleChain = RuleChain.outerRule((base, description) -> new org.junit.runners.model.Statement() { + @Override + public void evaluate() throws Throwable { + assumeFalse("FIPS mode requires security enabled; this test uses plain HTTP S3 fixtures", inFipsJvm()); + base.evaluate(); + } + }).around(clusterInstance); + + public static ElasticsearchCluster cluster = clusterInstance; private final String distributionMode; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/datasources/spi/StoragePath.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/datasources/spi/StoragePath.java index 7f92db7c491e4..91fa7d7d29c5e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/datasources/spi/StoragePath.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/datasources/spi/StoragePath.java @@ -70,16 +70,31 @@ public static StoragePath of(String location) { // Parse authority and path int authorityStart = schemeEnd + SCHEME_SEPARATOR.length(); - int pathStart = location.indexOf('/', authorityStart); + + // Handle file:// URIs that may contain Windows drive letters (e.g. file:///C:/path or file://C:\path) + // Normalize backslashes to forward slashes for file:// URIs before parsing + String toParse = location; + if (scheme.equals("file")) { + toParse = location.substring(0, authorityStart) + location.substring(authorityStart).replace('\\', '/'); + } + + int pathStart = toParse.indexOf('/', authorityStart); String authority; String path; if (pathStart < 0) { - authority = location.substring(authorityStart); + authority = toParse.substring(authorityStart); path = ""; } else { - authority = location.substring(authorityStart, pathStart); - path = location.substring(pathStart); + authority = toParse.substring(authorityStart, pathStart); + path = toParse.substring(pathStart); + } + + // For file:// URIs with Windows drive letters like file://C:/path, + // the drive letter ends up as the authority. Fold it back into the path. + if (scheme.equals("file") && authority.length() == 2 && Character.isLetter(authority.charAt(0)) && authority.charAt(1) == ':') { + path = "/" + authority + path; + authority = ""; } // Parse host and port from authority diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/datasources/spi/StoragePathTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/datasources/spi/StoragePathTests.java index 278f77918beb8..99436d7291fa1 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/datasources/spi/StoragePathTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/datasources/spi/StoragePathTests.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.esql.datasources.spi; +import org.elasticsearch.core.PathUtils; import org.elasticsearch.test.ESTestCase; @SuppressWarnings("RegexpMultiline") @@ -87,4 +88,43 @@ public void testGlobPartBraces() { StoragePath path = StoragePath.of("s3://b/data/*.{parquet,csv}"); assertEquals("*.{parquet,csv}", path.globPart()); } + + // -- file:// URI handling (including Windows paths) -- + + public void testFileUriUnixAbsolute() { + StoragePath path = StoragePath.of("file:///home/user/data.parquet"); + assertEquals("file", path.scheme()); + assertEquals("", path.host()); + assertEquals(-1, path.port()); + assertEquals("/home/user/data.parquet", path.path()); + } + + public void testFileUriWindowsDriveLetter() { + StoragePath path = StoragePath.of("file://C:/Users/data/file.txt"); + assertEquals("file", path.scheme()); + assertEquals("", path.host()); + assertEquals("/C:/Users/data/file.txt", path.path()); + } + + public void testFileUriWindowsBackslashes() { + StoragePath path = StoragePath.of("file://C:\\Users\\data\\file.txt"); + assertEquals("file", path.scheme()); + assertEquals("", path.host()); + assertEquals("/C:/Users/data/file.txt", path.path()); + } + + public void testFileUriWindowsTripleSlash() { + StoragePath path = StoragePath.of("file:///C:/path/to/file.parquet"); + assertEquals("file", path.scheme()); + assertEquals("", path.host()); + assertEquals("/C:/path/to/file.parquet", path.path()); + } + + public void testFileUriFunctionOnUnix() { + java.nio.file.Path p = PathUtils.get("/tmp/test/data.parquet"); + String uri = StoragePath.fileUri(p); + assertEquals("file:///tmp/test/data.parquet", uri); + StoragePath sp = StoragePath.of(uri); + assertEquals("/tmp/test/data.parquet", sp.path()); + } } From 0c58650ff6fd3c7e6c5d5c334b6b75885897f07a Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Tue, 3 Mar 2026 13:08:39 +0200 Subject: [PATCH 058/137] ESQL: Add extended distribution tests and fault injection for external sources (#143420) * ESQL: Add extended distribution tests and fault injection for external sources Extends the test coverage for external source distributed execution with property tests for weighted round-robin and coalescing, and adds fault injection infrastructure for testing resilience under storage failures. - ExtendedDistributionPropertyTests: weighted RR load balancing bounds, coalescing preservation, coalesced+distribution integration - FaultInjectionRetryTests: retry policy behavior under transient and persistent fault patterns (503, connection reset, timeout) - FaultInjectingS3HttpHandler: configurable S3 fault injection with countdown, path filtering, and auto-clearing - FaultInjectingS3HttpHandlerIT: real HTTP server tests for the handler Developed using AI-assisted tooling * Update docs/changelog/143420.yaml --- docs/changelog/143420.yaml | 5 + .../FaultInjectingS3HttpHandlerIT.java | 150 +++++++++++ .../FaultInjectingS3HttpHandler.java | 107 ++++++++ .../datasources/FaultInjectionRetryTests.java | 148 ++++++++++ .../ExtendedDistributionPropertyTests.java | 252 ++++++++++++++++++ 5 files changed, 662 insertions(+) create mode 100644 docs/changelog/143420.yaml create mode 100644 x-pack/plugin/esql/qa/server/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/multi_node/FaultInjectingS3HttpHandlerIT.java create mode 100644 x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/datasources/FaultInjectingS3HttpHandler.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/datasources/FaultInjectionRetryTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ExtendedDistributionPropertyTests.java diff --git a/docs/changelog/143420.yaml b/docs/changelog/143420.yaml new file mode 100644 index 0000000000000..17f2b43094a08 --- /dev/null +++ b/docs/changelog/143420.yaml @@ -0,0 +1,5 @@ +area: ES|QL +issues: [] +pr: 143420 +summary: Add extended distribution tests and fault injection for external sources +type: enhancement diff --git a/x-pack/plugin/esql/qa/server/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/multi_node/FaultInjectingS3HttpHandlerIT.java b/x-pack/plugin/esql/qa/server/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/multi_node/FaultInjectingS3HttpHandlerIT.java new file mode 100644 index 0000000000000..1f53bbbdbedb8 --- /dev/null +++ b/x-pack/plugin/esql/qa/server/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/multi_node/FaultInjectingS3HttpHandlerIT.java @@ -0,0 +1,150 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.qa.multi_node; + +import fixture.s3.S3ConsistencyModel; +import fixture.s3.S3HttpHandler; + +import com.sun.net.httpserver.HttpServer; + +import org.elasticsearch.common.bytes.BytesArray; +import org.elasticsearch.core.SuppressForbidden; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.esql.datasources.FaultInjectingS3HttpHandler; +import org.elasticsearch.xpack.esql.datasources.FaultInjectingS3HttpHandler.FaultType; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.InetSocketAddress; +import java.net.URI; +import java.nio.charset.StandardCharsets; + +/** + * Tests {@link FaultInjectingS3HttpHandler} using a real HTTP server to verify + * fault injection produces correct HTTP responses. + */ +@SuppressForbidden(reason = "uses HttpServer to test fault injection handler") +public class FaultInjectingS3HttpHandlerIT extends ESTestCase { + + public void testNoFaultReturnsNormalResponse() throws Exception { + S3HttpHandler s3Handler = new S3HttpHandler("bucket", S3ConsistencyModel.STRONG_MPUS); + s3Handler.blobs().put("/bucket/data.parquet", new BytesArray("test-content".getBytes(StandardCharsets.UTF_8))); + FaultInjectingS3HttpHandler handler = new FaultInjectingS3HttpHandler(s3Handler); + + try (TestHttpServer server = new TestHttpServer(handler)) { + HttpURLConnection conn = openConnection(server, "/bucket/data.parquet"); + assertEquals(200, conn.getResponseCode()); + } + } + + public void testHttp503FaultReturnsServiceUnavailable() throws Exception { + S3HttpHandler s3Handler = new S3HttpHandler("bucket", S3ConsistencyModel.STRONG_MPUS); + FaultInjectingS3HttpHandler handler = new FaultInjectingS3HttpHandler(s3Handler); + handler.setFault(FaultType.HTTP_503, 1); + + try (TestHttpServer server = new TestHttpServer(handler)) { + HttpURLConnection conn = openConnection(server, "/bucket/data.parquet"); + assertEquals(503, conn.getResponseCode()); + assertEquals(0, handler.remainingFaults()); + + // Next request should succeed (fault exhausted) + s3Handler.blobs().put("/bucket/data.parquet", new BytesArray("ok".getBytes(StandardCharsets.UTF_8))); + HttpURLConnection conn2 = openConnection(server, "/bucket/data.parquet"); + assertEquals(200, conn2.getResponseCode()); + } + } + + public void testHttp500FaultReturnsInternalError() throws Exception { + S3HttpHandler s3Handler = new S3HttpHandler("bucket", S3ConsistencyModel.STRONG_MPUS); + FaultInjectingS3HttpHandler handler = new FaultInjectingS3HttpHandler(s3Handler); + handler.setFault(FaultType.HTTP_500, 1); + + try (TestHttpServer server = new TestHttpServer(handler)) { + HttpURLConnection conn = openConnection(server, "/bucket/data.parquet"); + assertEquals(500, conn.getResponseCode()); + } + } + + public void testFaultCountdownDecrementsCorrectly() throws Exception { + S3HttpHandler s3Handler = new S3HttpHandler("bucket", S3ConsistencyModel.STRONG_MPUS); + s3Handler.blobs().put("/bucket/data.parquet", new BytesArray("ok".getBytes(StandardCharsets.UTF_8))); + FaultInjectingS3HttpHandler handler = new FaultInjectingS3HttpHandler(s3Handler); + handler.setFault(FaultType.HTTP_503, 3); + + try (TestHttpServer server = new TestHttpServer(handler)) { + for (int i = 0; i < 3; i++) { + HttpURLConnection conn = openConnection(server, "/bucket/data.parquet"); + assertEquals("Request " + i + " should fail", 503, conn.getResponseCode()); + assertEquals(2 - i, handler.remainingFaults()); + } + HttpURLConnection conn = openConnection(server, "/bucket/data.parquet"); + assertEquals("After faults exhausted, should succeed", 200, conn.getResponseCode()); + } + } + + public void testPathFilterOnlyAffectsMatchingPaths() throws Exception { + S3HttpHandler s3Handler = new S3HttpHandler("bucket", S3ConsistencyModel.STRONG_MPUS); + s3Handler.blobs().put("/bucket/metadata.json", new BytesArray("meta".getBytes(StandardCharsets.UTF_8))); + FaultInjectingS3HttpHandler handler = new FaultInjectingS3HttpHandler(s3Handler); + handler.setFault(FaultType.HTTP_503, 10, path -> path.endsWith(".parquet")); + + try (TestHttpServer server = new TestHttpServer(handler)) { + HttpURLConnection conn = openConnection(server, "/bucket/metadata.json"); + assertEquals("Non-matching path should succeed", 200, conn.getResponseCode()); + assertEquals("Fault count unchanged for non-matching path", 10, handler.remainingFaults()); + } + } + + public void testClearFaultStopsInjection() throws Exception { + S3HttpHandler s3Handler = new S3HttpHandler("bucket", S3ConsistencyModel.STRONG_MPUS); + s3Handler.blobs().put("/bucket/data.parquet", new BytesArray("ok".getBytes(StandardCharsets.UTF_8))); + FaultInjectingS3HttpHandler handler = new FaultInjectingS3HttpHandler(s3Handler); + handler.setFault(FaultType.HTTP_503, 100); + + try (TestHttpServer server = new TestHttpServer(handler)) { + HttpURLConnection conn1 = openConnection(server, "/bucket/data.parquet"); + assertEquals(503, conn1.getResponseCode()); + + handler.clearFault(); + + HttpURLConnection conn2 = openConnection(server, "/bucket/data.parquet"); + assertEquals(200, conn2.getResponseCode()); + } + } + + @SuppressForbidden(reason = "test HTTP server for fault injection") + private static HttpURLConnection openConnection(TestHttpServer server, String path) throws IOException { + URI uri = URI.create("http://localhost:" + server.port() + path); + HttpURLConnection conn = (HttpURLConnection) uri.toURL().openConnection(); + conn.setRequestMethod("GET"); + conn.setConnectTimeout(5000); + conn.setReadTimeout(5000); + conn.connect(); + return conn; + } + + @SuppressForbidden(reason = "test HTTP server for fault injection") + private static class TestHttpServer implements AutoCloseable { + private final HttpServer server; + + TestHttpServer(FaultInjectingS3HttpHandler handler) throws IOException { + server = HttpServer.create(new InetSocketAddress(0), 0); + server.createContext("/", handler); + server.start(); + } + + int port() { + return server.getAddress().getPort(); + } + + @Override + public void close() { + server.stop(0); + } + } +} diff --git a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/datasources/FaultInjectingS3HttpHandler.java b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/datasources/FaultInjectingS3HttpHandler.java new file mode 100644 index 0000000000000..3ddabd2f70633 --- /dev/null +++ b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/datasources/FaultInjectingS3HttpHandler.java @@ -0,0 +1,107 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.datasources; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; + +import org.elasticsearch.core.SuppressForbidden; +import org.elasticsearch.logging.LogManager; +import org.elasticsearch.logging.Logger; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Predicate; + +/** + * HTTP handler wrapper that injects configurable faults into S3 requests. + * Supports HTTP 503, HTTP 500, and connection reset fault types with + * countdown-based auto-clearing and path-based filtering. + */ +@SuppressForbidden(reason = "uses HttpServer to emulate a faulty S3 endpoint") +public class FaultInjectingS3HttpHandler implements HttpHandler { + + private static final Logger logger = LogManager.getLogger(FaultInjectingS3HttpHandler.class); + + private final HttpHandler delegate; + private volatile FaultConfig activeFault; + + public FaultInjectingS3HttpHandler(HttpHandler delegate) { + if (delegate == null) { + throw new IllegalArgumentException("delegate must not be null"); + } + this.delegate = delegate; + } + + public void setFault(FaultType type, int count) { + setFault(type, count, path -> true); + } + + public void setFault(FaultType type, int count, Predicate pathFilter) { + this.activeFault = new FaultConfig(type, new AtomicInteger(count), pathFilter); + } + + public void clearFault() { + this.activeFault = null; + } + + public int remainingFaults() { + FaultConfig fault = this.activeFault; + return fault == null ? 0 : fault.remaining.get(); + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + FaultConfig fault = this.activeFault; + if (fault != null && fault.remaining.get() > 0) { + String path = exchange.getRequestURI().getPath(); + if (fault.pathFilter.test(path) && fault.remaining.decrementAndGet() >= 0) { + logger.debug("injecting fault [{}] for path [{}], remaining [{}]", fault.type, path, fault.remaining.get()); + injectFault(exchange, fault.type); + return; + } + } + delegate.handle(exchange); + } + + private static void injectFault(HttpExchange exchange, FaultType type) throws IOException { + switch (type) { + case HTTP_503 -> sendErrorResponse(exchange, 503, "Service Unavailable", "SlowDown", "Reduce your request rate"); + case HTTP_500 -> sendErrorResponse(exchange, 500, "Internal Server Error", "InternalError", "Internal server error"); + case CONNECTION_RESET -> { + exchange.close(); + } + } + } + + private static void sendErrorResponse(HttpExchange exchange, int statusCode, String statusText, String code, String message) + throws IOException { + String body = "" + + "" + + code + + "" + + message + + ""; + byte[] bytes = body.getBytes(StandardCharsets.UTF_8); + exchange.getResponseHeaders().set("Content-Type", "application/xml"); + exchange.sendResponseHeaders(statusCode, bytes.length); + try (OutputStream os = exchange.getResponseBody()) { + os.write(bytes); + } + } + + public enum FaultType { + HTTP_503, + HTTP_500, + CONNECTION_RESET + } + + private record FaultConfig(FaultType type, AtomicInteger remaining, Predicate pathFilter) {} +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/datasources/FaultInjectionRetryTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/datasources/FaultInjectionRetryTests.java new file mode 100644 index 0000000000000..825f0e6512d03 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/datasources/FaultInjectionRetryTests.java @@ -0,0 +1,148 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.datasources; + +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.esql.datasources.spi.StoragePath; + +import java.io.IOException; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Tests that the retry policy correctly handles transient fault patterns + * matching what {@code FaultInjectingS3HttpHandler} produces: a configurable + * number of failures followed by success. + */ +public class FaultInjectionRetryTests extends ESTestCase { + + public void testTransientFaultsRecoverWithinRetryBudget() throws IOException { + int faultCount = between(1, 2); + RetryPolicy policy = new RetryPolicy(3, 1, 10); + AtomicInteger calls = new AtomicInteger(); + StoragePath path = StoragePath.of("s3://bucket/data.parquet"); + + String result = policy.execute(() -> { + if (calls.incrementAndGet() <= faultCount) { + throw new IOException("503 Service Unavailable"); + } + return "data"; + }, "GET_OBJECT", path); + + assertEquals("data", result); + assertEquals(faultCount + 1, calls.get()); + } + + public void testPersistentFaultsExhaustRetryBudget() { + RetryPolicy policy = new RetryPolicy(3, 1, 10); + AtomicInteger calls = new AtomicInteger(); + StoragePath path = StoragePath.of("s3://bucket/data.parquet"); + + IOException ex = expectThrows(IOException.class, () -> policy.execute(() -> { + calls.incrementAndGet(); + throw new IOException("503 Service Unavailable"); + }, "GET_OBJECT", path)); + + assertTrue(ex.getMessage().contains("503")); + assertEquals(4, calls.get()); + } + + public void testConnectionResetIsRetried() throws IOException { + RetryPolicy policy = new RetryPolicy(3, 1, 10); + AtomicInteger calls = new AtomicInteger(); + StoragePath path = StoragePath.of("s3://bucket/data.parquet"); + + String result = policy.execute(() -> { + if (calls.incrementAndGet() == 1) { + throw new SocketException("Connection reset"); + } + return "recovered"; + }, "GET_OBJECT", path); + + assertEquals("recovered", result); + assertEquals(2, calls.get()); + } + + public void testNonRetryableFaultFailsImmediately() { + RetryPolicy policy = new RetryPolicy(3, 1, 10); + AtomicInteger calls = new AtomicInteger(); + StoragePath path = StoragePath.of("s3://bucket/secret.parquet"); + + IOException ex = expectThrows(IOException.class, () -> policy.execute(() -> { + calls.incrementAndGet(); + throw new IOException("403 Access Denied"); + }, "GET_OBJECT", path)); + + assertTrue(ex.getMessage().contains("403")); + assertEquals(1, calls.get()); + } + + public void testTimeoutIsRetried() throws IOException { + RetryPolicy policy = new RetryPolicy(3, 1, 10); + AtomicInteger calls = new AtomicInteger(); + StoragePath path = StoragePath.of("s3://bucket/data.parquet"); + + String result = policy.execute(() -> { + if (calls.incrementAndGet() <= 2) { + throw new SocketTimeoutException("Read timed out"); + } + return "ok"; + }, "GET_OBJECT", path); + + assertEquals("ok", result); + assertEquals(3, calls.get()); + } + + public void testCountdownFaultPattern() throws IOException { + int totalFaults = between(1, 3); + RetryPolicy policy = new RetryPolicy(totalFaults + 1, 1, 10); + AtomicInteger faultCounter = new AtomicInteger(totalFaults); + AtomicInteger calls = new AtomicInteger(); + StoragePath path = StoragePath.of("s3://bucket/data.parquet"); + + String result = policy.execute(() -> { + calls.incrementAndGet(); + if (faultCounter.decrementAndGet() >= 0) { + throw new IOException("503 Service Unavailable"); + } + return "success"; + }, "GET_OBJECT", path); + + assertEquals("success", result); + assertEquals(totalFaults + 1, calls.get()); + } + + public void testSuccessfulCallReturnsImmediately() throws IOException { + RetryPolicy policy = new RetryPolicy(3, 1, 10); + AtomicInteger calls = new AtomicInteger(); + StoragePath path = StoragePath.of("s3://bucket/metadata.json"); + + String result = policy.execute(() -> { + calls.incrementAndGet(); + return "metadata"; + }, "GET_OBJECT", path); + + assertEquals("metadata", result); + assertEquals(1, calls.get()); + } + + public void testRetryPolicyWithZeroRetriesNeverRetries() { + RetryPolicy policy = RetryPolicy.NONE; + AtomicInteger calls = new AtomicInteger(); + StoragePath path = StoragePath.of("s3://bucket/data.parquet"); + + IOException ex = expectThrows(IOException.class, () -> policy.execute(() -> { + calls.incrementAndGet(); + throw new IOException("503 Service Unavailable"); + }, "GET_OBJECT", path)); + + assertTrue(ex.getMessage().contains("503")); + assertEquals(1, calls.get()); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ExtendedDistributionPropertyTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ExtendedDistributionPropertyTests.java new file mode 100644 index 0000000000000..7fa16311d403d --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ExtendedDistributionPropertyTests.java @@ -0,0 +1,252 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.plugin; + +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.node.DiscoveryNodeUtils; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.esql.datasources.CoalescedSplit; +import org.elasticsearch.xpack.esql.datasources.FileSplit; +import org.elasticsearch.xpack.esql.datasources.SplitCoalescer; +import org.elasticsearch.xpack.esql.datasources.spi.ExternalSplit; +import org.elasticsearch.xpack.esql.datasources.spi.StoragePath; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.elasticsearch.cluster.node.DiscoveryNodeRole.DATA_HOT_NODE_ROLE; + +/** + * Extended property tests for weighted round-robin distribution, split coalescing, + * and their interaction. Validates invariants that must hold regardless of input + * size, node count, or split characteristics. + */ +public class ExtendedDistributionPropertyTests extends ESTestCase { + + // --- Weighted Round-Robin Properties --- + + public void testWeightedAssignsAllSplitsExactlyOnce() { + int splitCount = between(2, 200); + int nodeCount = between(1, 20); + List splits = createSizedSplits(splitCount); + List nodes = createNodeList(nodeCount); + + ExternalDistributionPlan plan = WeightedRoundRobinStrategy.assignByWeight(splits, nodes); + + assertTrue(plan.distributed()); + Set assigned = new HashSet<>(); + int totalAssigned = 0; + for (List nodeSplits : plan.nodeAssignments().values()) { + for (ExternalSplit split : nodeSplits) { + assertTrue("Split assigned more than once", assigned.add(split)); + } + totalAssigned += nodeSplits.size(); + } + assertEquals("All splits must be assigned", splitCount, totalAssigned); + } + + public void testWeightedLoadBalancing() { + int splitCount = between(10, 200); + int nodeCount = between(2, 10); + List splits = createSizedSplits(splitCount); + List nodes = createNodeList(nodeCount); + + ExternalDistributionPlan plan = WeightedRoundRobinStrategy.assignByWeight(splits, nodes); + + long totalSize = 0; + long maxNodeLoad = 0; + for (ExternalSplit split : splits) { + totalSize += split.estimatedSizeInBytes(); + } + for (List nodeSplits : plan.nodeAssignments().values()) { + long nodeLoad = 0; + for (ExternalSplit split : nodeSplits) { + nodeLoad += split.estimatedSizeInBytes(); + } + maxNodeLoad = Math.max(maxNodeLoad, nodeLoad); + } + + long idealLoad = totalSize / nodeCount; + long largestSplit = splits.stream().mapToLong(ExternalSplit::estimatedSizeInBytes).max().orElse(0); + // LPT guarantees max load <= idealLoad + largestSplit + assertTrue( + "Max node load " + maxNodeLoad + " exceeds LPT bound " + (idealLoad + largestSplit), + maxNodeLoad <= idealLoad + largestSplit + ); + } + + public void testWeightedIsDeterministic() { + int splitCount = between(5, 50); + int nodeCount = between(2, 8); + List splits = createSizedSplits(splitCount); + List nodes = createNodeList(nodeCount); + + ExternalDistributionPlan plan1 = WeightedRoundRobinStrategy.assignByWeight(splits, nodes); + ExternalDistributionPlan plan2 = WeightedRoundRobinStrategy.assignByWeight(splits, nodes); + + assertEquals(plan1.nodeAssignments().keySet(), plan2.nodeAssignments().keySet()); + for (String nodeId : plan1.nodeAssignments().keySet()) { + assertEquals( + "Node " + nodeId + " must get same splits on both runs", + plan1.nodeAssignments().get(nodeId), + plan2.nodeAssignments().get(nodeId) + ); + } + } + + public void testWeightedSingleLargeSplitGoesToLeastLoaded() { + List nodes = createNodeList(3); + List splits = new ArrayList<>(); + splits.add(createSizedSplit(0, 10_000_000)); + for (int i = 1; i <= 10; i++) { + splits.add(createSizedSplit(i, 1000)); + } + + ExternalDistributionPlan plan = WeightedRoundRobinStrategy.assignByWeight(splits, nodes); + + boolean largestFound = false; + for (List nodeSplits : plan.nodeAssignments().values()) { + for (ExternalSplit split : nodeSplits) { + if (split.estimatedSizeInBytes() == 10_000_000) { + largestFound = true; + } + } + } + assertTrue("Largest split must be assigned", largestFound); + } + + // --- Coalescing Properties --- + + public void testCoalescingPreservesAllFiles() { + int splitCount = between(SplitCoalescer.COALESCING_THRESHOLD + 1, 500); + List original = createSizedSplits(splitCount); + + List coalesced = SplitCoalescer.coalesce(original); + + assertTrue("Coalescing should reduce split count", coalesced.size() < original.size()); + + List expanded = expandCoalesced(coalesced); + assertEquals("All original files must be preserved", splitCount, expanded.size()); + + long originalTotal = original.stream().mapToLong(ExternalSplit::estimatedSizeInBytes).sum(); + long expandedTotal = expanded.stream().mapToLong(ExternalSplit::estimatedSizeInBytes).sum(); + assertEquals("Total size must be preserved", originalTotal, expandedTotal); + } + + public void testCoalescingBelowThresholdIsNoOp() { + int splitCount = between(1, SplitCoalescer.COALESCING_THRESHOLD); + List original = createSizedSplits(splitCount); + + List result = SplitCoalescer.coalesce(original); + + assertSame("Below threshold, coalescing must return the same list", original, result); + } + + public void testCoalescedSplitSizeEqualsChildrenSum() { + int childCount = between(2, 20); + List children = createSizedSplits(childCount); + CoalescedSplit coalesced = new CoalescedSplit("parquet", children); + + long expectedSize = children.stream().mapToLong(ExternalSplit::estimatedSizeInBytes).sum(); + assertEquals("CoalescedSplit size must equal sum of children", expectedSize, coalesced.estimatedSizeInBytes()); + } + + // --- Coalescing + Distribution Integration --- + + public void testCoalescedSplitsDistributeCorrectly() { + int splitCount = between(SplitCoalescer.COALESCING_THRESHOLD + 1, 200); + int nodeCount = between(2, 8); + List original = createSizedSplits(splitCount); + List nodes = createNodeList(nodeCount); + + List coalesced = SplitCoalescer.coalesce(original); + ExternalDistributionPlan plan = WeightedRoundRobinStrategy.assignByWeight(coalesced, nodes); + + assertTrue(plan.distributed()); + + int totalAssigned = 0; + for (List nodeSplits : plan.nodeAssignments().values()) { + totalAssigned += nodeSplits.size(); + } + assertEquals("All coalesced splits must be assigned", coalesced.size(), totalAssigned); + + List allExpanded = new ArrayList<>(); + for (List nodeSplits : plan.nodeAssignments().values()) { + allExpanded.addAll(expandCoalesced(nodeSplits)); + } + assertEquals("Expanding all assigned splits must yield original count", splitCount, allExpanded.size()); + } + + public void testRoundRobinAndWeightedAgreeOnCompleteness() { + int splitCount = between(2, 100); + int nodeCount = between(2, 10); + List splits = createSizedSplits(splitCount); + List nodes = createNodeList(nodeCount); + + ExternalDistributionPlan rrPlan = RoundRobinStrategy.assignRoundRobin(splits, nodes); + ExternalDistributionPlan wrPlan = WeightedRoundRobinStrategy.assignByWeight(splits, nodes); + + int rrTotal = countAssigned(rrPlan); + int wrTotal = countAssigned(wrPlan); + assertEquals("Both strategies must assign all splits", splitCount, rrTotal); + assertEquals("Both strategies must assign all splits", splitCount, wrTotal); + } + + // --- Helpers --- + + private static List expandCoalesced(List splits) { + List result = new ArrayList<>(); + for (ExternalSplit split : splits) { + if (split instanceof CoalescedSplit cs) { + result.addAll(cs.children()); + } else { + result.add(split); + } + } + return result; + } + + private static int countAssigned(ExternalDistributionPlan plan) { + int total = 0; + for (List nodeSplits : plan.nodeAssignments().values()) { + total += nodeSplits.size(); + } + return total; + } + + private static List createSizedSplits(int count) { + List splits = new ArrayList<>(); + for (int i = 0; i < count; i++) { + splits.add(createSizedSplit(i, 1024L * (i + 1))); + } + return splits; + } + + private static ExternalSplit createSizedSplit(int index, long sizeBytes) { + return new FileSplit( + "parquet", + StoragePath.of("s3://bucket/file" + index + ".parquet"), + 0, + sizeBytes, + ".parquet", + Map.of(), + Map.of() + ); + } + + private static List createNodeList(int count) { + List nodes = new ArrayList<>(); + for (int i = 0; i < count; i++) { + nodes.add(DiscoveryNodeUtils.builder("node-" + i).roles(Set.of(DATA_HOT_NODE_ROLE)).build()); + } + return nodes; + } +} From 1b326b18a3502111333e73c24c3089bf24d6499a Mon Sep 17 00:00:00 2001 From: Luigi Dell'Aquila Date: Tue, 3 Mar 2026 12:16:10 +0100 Subject: [PATCH 059/137] Fix SQL client parsing of array header values (#143408) --- docs/changelog/143408.yaml | 7 ++++++ .../xpack/sql/client/RemoteFailure.java | 14 +++++++++-- .../xpack/sql/client/RemoteFailureTests.java | 12 ++++++++++ .../missing_auth_multiple_schemes.json | 23 +++++++++++++++++++ 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 docs/changelog/143408.yaml create mode 100644 x-pack/plugin/sql/sql-client/src/test/resources/remote_failure/missing_auth_multiple_schemes.json diff --git a/docs/changelog/143408.yaml b/docs/changelog/143408.yaml new file mode 100644 index 0000000000000..1d0e67b36b007 --- /dev/null +++ b/docs/changelog/143408.yaml @@ -0,0 +1,7 @@ +area: SQL +issues: + - 143018 + - 143019 +pr: 143408 +summary: Fix SQL client parsing of array header values +type: bug diff --git a/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/RemoteFailure.java b/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/RemoteFailure.java index abf1228b5945c..6b16fb107f6ba 100644 --- a/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/RemoteFailure.java +++ b/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/RemoteFailure.java @@ -269,10 +269,20 @@ private static Map parseHeaders(JsonParser parser) throws IOExce } String name = parser.getText(); token = parser.nextToken(); - if (token != JsonToken.VALUE_STRING) { + String value; + if (token == JsonToken.VALUE_STRING) { + value = parser.getText(); + } else if (token == JsonToken.START_ARRAY) { + List values = new ArrayList<>(); + while ((token = parser.nextToken()) != JsonToken.END_ARRAY) { + if (token == JsonToken.VALUE_STRING) { + values.add(parser.getText()); + } + } + value = String.join(", ", values); + } else { throw new IOException("expected header value but was [" + token + "][" + parser.getText() + "]"); } - String value = parser.getText(); headers.put(name, value); } diff --git a/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/RemoteFailureTests.java b/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/RemoteFailureTests.java index 258a738a076c8..d369eb9b0b961 100644 --- a/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/RemoteFailureTests.java +++ b/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/RemoteFailureTests.java @@ -64,6 +64,18 @@ public void testParseMissingAuth() throws IOException { assertEquals(singletonMap("WWW-Authenticate", "Basic realm=\"security\", charset=\"UTF-8\""), failure.headers()); } + public void testParseMissingAuthMultipleSchemes() throws IOException { + RemoteFailure failure = parse("missing_auth_multiple_schemes.json"); + assertEquals("security_exception", failure.type()); + assertEquals( + "unable to authenticate with provided credentials and anonymous access is not allowed for this request", + failure.reason() + ); + assertThat(failure.remoteTrace(), containsString("AuthenticationService.authenticate")); + assertNull(failure.cause()); + assertEquals(singletonMap("WWW-Authenticate", "Basic realm=\"security\", charset=\"UTF-8\", ApiKey"), failure.headers()); + } + public void testNoError() { IOException e = expectThrows(IOException.class, () -> parse("no_error.json")); assertEquals( diff --git a/x-pack/plugin/sql/sql-client/src/test/resources/remote_failure/missing_auth_multiple_schemes.json b/x-pack/plugin/sql/sql-client/src/test/resources/remote_failure/missing_auth_multiple_schemes.json new file mode 100644 index 0000000000000..3d43a2d7c8af9 --- /dev/null +++ b/x-pack/plugin/sql/sql-client/src/test/resources/remote_failure/missing_auth_multiple_schemes.json @@ -0,0 +1,23 @@ +{ + "error" : { + "root_cause" : [ + { + "type" : "security_exception", + "reason" : "unable to authenticate with provided credentials and anonymous access is not allowed for this request", + "additional_unsuccessful_credentials" : "API key: Illegal base64 character 5f", + "header" : { + "WWW-Authenticate" : ["Basic realm=\"security\", charset=\"UTF-8\"", "ApiKey"] + }, + "stack_trace" : "ElasticsearchSecurityException[unable to authenticate]\n\tat org.elasticsearch.xpack.security.authc.AuthenticationService.authenticate(AuthenticationService.java:99)" + } + ], + "type" : "security_exception", + "reason" : "unable to authenticate with provided credentials and anonymous access is not allowed for this request", + "additional_unsuccessful_credentials" : "API key: Illegal base64 character 5f", + "header" : { + "WWW-Authenticate" : ["Basic realm=\"security\", charset=\"UTF-8\"", "ApiKey"] + }, + "stack_trace" : "ElasticsearchSecurityException[unable to authenticate]\n\tat org.elasticsearch.xpack.security.authc.AuthenticationService.authenticate(AuthenticationService.java:99)" + }, + "status" : 401 +} From 84b10b37c5923391921b45921e8bcf1d6b11fb2d Mon Sep 17 00:00:00 2001 From: Oleg Lvovitch Date: Tue, 3 Mar 2026 12:54:43 +0000 Subject: [PATCH 060/137] Fix CSV-escaped quotes in generated docs examples (#143449) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix CSV-escaped quotes rendering in generated docs examples DocsV3Support.renderTableLine() now unescapes RFC 4180 CSV quoting (strips outer quote delimiters and replaces "" with ") so that JSON strings in function example tables render correctly — e.g. {"key":"value"} instead of {""key"":""value""}. Affects json_extract and to_tdigest doc examples. * Refine CSV unescaping to only unescape RFC 4180 doubled quotes; add tests The previous approach stripped outer quotes from ALL quoted values, breaking simple quoted values like "POINT(...)" and "foo". Now only cells with actual RFC 4180 doubled-quote escaping ("") are unescaped, leaving simple quoted values unchanged. Added tests: testRenderingExampleResultCsvJsonUnescaping verifies JSON unescaping works, testRenderingExampleResultSimpleQuotesPreserved verifies simple quoted values are not modified. Also adds changelog YAML for the PR. --- docs/changelog/143449.yaml | 5 ++++ .../functions/examples/json_extract.md | 10 +++---- .../functions/examples/to_tdigest.md | 2 +- .../expression/function/DocsV3Support.java | 11 +++++++- .../function/DocsV3SupportTests.java | 28 +++++++++++++++++++ 5 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 docs/changelog/143449.yaml diff --git a/docs/changelog/143449.yaml b/docs/changelog/143449.yaml new file mode 100644 index 0000000000000..016b384e43a0e --- /dev/null +++ b/docs/changelog/143449.yaml @@ -0,0 +1,5 @@ +pr: 143449 +summary: Fix CSV-escaped quotes rendering in generated ES|QL docs examples +area: ES|QL +type: bug +issues: [] diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/json_extract.md b/docs/reference/query-languages/esql/_snippets/functions/examples/json_extract.md index b3f27fe775896..ae41c037feec7 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/json_extract.md +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/json_extract.md @@ -9,7 +9,7 @@ ROW log = """{"severity":"ERROR","body":"Payment processing failed"}""" | log:keyword | severity:keyword | | --- | --- | -| "{""severity"":""ERROR"",""body"":""Payment processing failed""}" | ERROR | +| {"severity":"ERROR","body":"Payment processing failed"} | ERROR | The `$` prefix is optional — this query produces the same result as the previous example: @@ -20,7 +20,7 @@ ROW log = """{"severity":"ERROR","body":"Payment processing failed"}""" | log:keyword | severity:keyword | | --- | --- | -| "{""severity"":""ERROR"",""body"":""Payment processing failed""}" | ERROR | +| {"severity":"ERROR","body":"Payment processing failed"} | ERROR | To extract a deeply nested value, use dot-notation: @@ -31,7 +31,7 @@ ROW log = """{"resource":{"service":{"name":"order-service"}}}""" | log:keyword | svc:keyword | | --- | --- | -| "{""resource"":{""service"":{""name"":""order-service""}}}" | order-service | +| {"resource":{"service":{"name":"order-service"}}} | order-service | Keys that contain dots (common in OpenTelemetry semantic conventions) require quoted bracket notation — here `service.name` is a single key, not a nested path: @@ -58,7 +58,7 @@ ROW log = """{"spans":[{"name":"auth","duration":12},{"name":"db-query","duratio | log:keyword | span:keyword | | --- | --- | -| "{""spans"":[{""name"":""auth"",""duration"":12},{""name"":""db-query"",""duration"":45}]}" | db-query | +| {"spans":[{"name":"auth","duration":12},{"name":"db-query","duration":45}]} | db-query | When the extracted value is an object or array, it is returned as a JSON string: @@ -69,7 +69,7 @@ ROW log = """{"resource":{"service.name":"api-gateway","host.name":"api-server-0 | log:keyword | resource:keyword | | --- | --- | -| "{""resource"":{""service.name"":""api-gateway"",""host.name"":""api-server-03""},""severity"":""INFO""}" | "{""service.name"":""api-gateway"",""host.name"":""api-server-03""}" | +| {"resource":{"service.name":"api-gateway","host.name":"api-server-03"},"severity":"INFO"} | {"service.name":"api-gateway","host.name":"api-server-03"} | To extract from a top-level JSON array, use a bracket index on the root element: diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/to_tdigest.md b/docs/reference/query-languages/esql/_snippets/functions/examples/to_tdigest.md index dad4698c92571..731e6683ac2e1 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/to_tdigest.md +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/to_tdigest.md @@ -12,6 +12,6 @@ FROM histogram_standard_index | responseTime:histogram | tdigest:tdigest | | --- | --- | -| "{""values"":[0.1,0.2,0.3,0.4,0.5], ""counts"":[3,7,23,12,6]}" | "{""min"": 0.1, ""max"": 0.5, ""sum"": 16.4, ""centroids"":[0.1,0.2,0.3,0.4,0.5], ""counts"":[3,7,23,12,6]}" | +| {"values":[0.1,0.2,0.3,0.4,0.5], "counts":[3,7,23,12,6]} | {"min": 0.1, "max": 0.5, "sum": 16.4, "centroids":[0.1,0.2,0.3,0.4,0.5], "counts":[3,7,23,12,6]} | diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/DocsV3Support.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/DocsV3Support.java index f067bc654d2ad..c654ec50db426 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/DocsV3Support.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/DocsV3Support.java @@ -1896,8 +1896,17 @@ private String renderTableLine(String[] columns) { if (i > 0) { sb.append(" | "); } + String cell = columns[i].trim(); + // Unescape RFC 4180 CSV-quoted values that contain doubled quotes (""). + // In CSV spec results, a value like "{""key"":""val""}" uses outer " as field delimiters + // and "" as escaped ". We strip the delimiters and unescape so JSON renders correctly + // in docs (e.g. {"key":"value"} instead of {""key"":""value""}). + // Simple quoted values like "POINT(...)" have no "" inside and are left unchanged. + if (cell.startsWith("\"") && cell.endsWith("\"") && cell.substring(1, cell.length() - 1).contains("\"\"")) { + cell = cell.substring(1, cell.length() - 1).replace("\"\"", "\""); + } // Some cells have regex content (see CATEGORIZE), so we need to escape this - sb.append(columns[i].trim().replaceAll("\\.\\*", ".\\\\*")); + sb.append(cell.replaceAll("\\.\\*", ".\\\\*")); } return sb.append(" |\n").toString(); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/DocsV3SupportTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/DocsV3SupportTests.java index 4b3775f8c3dbf..0fb07be3cf740 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/DocsV3SupportTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/DocsV3SupportTests.java @@ -213,6 +213,34 @@ public void testRenderingExampleResultRaw() throws IOException { assertThat(results, equalTo(expectedResults)); } + /** + * Verify that RFC 4180 CSV-quoted values with doubled quotes are properly unescaped, + * so JSON strings render correctly in docs instead of showing {""key"":""value""}. + */ + public void testRenderingExampleResultCsvJsonUnescaping() throws IOException { + String expectedResults = """ + | log:keyword | severity:keyword | + | --- | --- | + | {"severity":"ERROR","body":"Payment processing failed"} | ERROR | + """; + String results = docs.loadExample("json_extract.csv-spec", "json_extract-result"); + assertThat(results, equalTo(expectedResults)); + } + + /** + * Verify that simple quoted values (no doubled quotes inside) are preserved as-is. + * Only values with "" (RFC 4180 escaping) should be unescaped. + */ + public void testRenderingExampleResultSimpleQuotesPreserved() throws IOException { + String expectedResults = """ + | wkt:keyword | pt:geo_point | + | --- | --- | + | "POINT(42.97109630194 14.7552534413725)" | POINT(42.97109630194 14.7552534413725) | + """; + String results = docs.loadExample("spatial.csv-spec", "to_geopoint-str-result"); + assertThat(results, equalTo(expectedResults)); + } + public void testRenderingExampleRaw2() throws IOException { String expectedExample = """ ROW n=1 From 17d86a78b9039177794aebffd25b53d6996b33c4 Mon Sep 17 00:00:00 2001 From: Ioana Tagirta Date: Tue, 3 Mar 2026 14:04:52 +0100 Subject: [PATCH 061/137] Fix MMROperatorTests (#143453) --- muted-tests.yml | 6 ------ .../compute/operator/MMROperatorTests.java | 11 ++--------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/muted-tests.yml b/muted-tests.yml index e7c11a4c9cd1e..ce0c2a16965ef 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -315,15 +315,9 @@ tests: - class: org.elasticsearch.compute.lucene.read.ValuesSourceReaderOperatorTests method: testWithNulls issue: https://github.com/elastic/elasticsearch/issues/142434 -- class: org.elasticsearch.compute.operator.MMROperatorTests - method: testSimpleLargeInput - issue: https://github.com/elastic/elasticsearch/issues/142437 - class: org.elasticsearch.xpack.esql.common.spatial.H3SphericalGeometryTests method: testIndexPoints issue: https://github.com/elastic/elasticsearch/issues/142439 -- class: org.elasticsearch.compute.operator.MMROperatorTests - method: testSimpleSmallInput - issue: https://github.com/elastic/elasticsearch/issues/142436 - class: org.elasticsearch.xpack.esql.core.util.RemoteClusterUtilsTests method: testQualifyAndJoinIndices issue: https://github.com/elastic/elasticsearch/issues/142442 diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/MMROperatorTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/MMROperatorTests.java index 7bbead4e0a4a6..07c18686d7f81 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/MMROperatorTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/MMROperatorTests.java @@ -22,9 +22,6 @@ import static org.hamcrest.Matchers.equalTo; public class MMROperatorTests extends OperatorTestCase { - - public static double NULL_BLOCK_CHANCE = 0.05; - static List TEST_VECTORS = List.of( new float[] { 0.4f, 0.2f, 0.4f, 0.4f }, new float[] { 0.4f, 0.2f, 0.3f, 0.3f }, @@ -53,13 +50,9 @@ protected int remaining() { @Override protected Page createPage(int positionOffset, int length) { length = Integer.min(length, remaining()); + currentPosition += length; var blocks = new Block[1]; - if (randomDouble() < NULL_BLOCK_CHANCE) { - blocks[0] = blockFactory.newConstantNullBlock(length); - return new Page(blocks); - } - float[] vectors = new float[length * 4]; int[] vectorPositions = new int[length + 1]; int vectorIndex = 0; @@ -77,7 +70,7 @@ protected Page createPage(int positionOffset, int length) { blocks[0] = blockFactory.newFloatArrayBlock(vectors, length, vectorPositions, new BitSet(), Block.MvOrdering.UNORDERED); } catch (Exception e) { throw new RuntimeException(e); - } finally {} + } finish(); return new Page(blocks); From df85dbffde01f6a014e6e77ffeaaaed5cb6fc082 Mon Sep 17 00:00:00 2001 From: Liam Thompson Date: Tue, 3 Mar 2026 14:11:49 +0100 Subject: [PATCH 062/137] [DOCS] Fix ES|QL function and commands lists versioning metadata (#143402) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix ES|QL function list versioning metadata Audit all _snippets/lists/ files against Java @FunctionAppliesTo annotations. Adds missing applies_to tags, corrects wrong versions, and applies cumulative preview→ga tags where functions graduated. Also adds missing applies_to front matter to time-series-aggregation-functions.md landing page. * update tags on commands lists --- .../_snippets/lists/aggregation-functions.md | 6 +++--- .../esql/_snippets/lists/date-time-functions.md | 6 +++--- .../_snippets/lists/dense-vector-functions.md | 14 +++++++------- .../esql/_snippets/lists/grouping-functions.md | 4 ++-- .../esql/_snippets/lists/math-functions.md | 6 +++--- .../esql/_snippets/lists/mv-functions.md | 4 ++-- .../esql/_snippets/lists/processing-commands.md | 16 ++++++++-------- .../esql/_snippets/lists/search-functions.md | 14 +++++++------- .../esql/_snippets/lists/source-commands.md | 2 +- .../esql/_snippets/lists/string-functions.md | 12 ++++++------ .../lists/time-series-aggregation-functions.md | 2 +- .../_snippets/lists/type-conversion-functions.md | 2 +- .../time-series-aggregation-functions.md | 3 +++ 13 files changed, 47 insertions(+), 44 deletions(-) diff --git a/docs/reference/query-languages/esql/_snippets/lists/aggregation-functions.md b/docs/reference/query-languages/esql/_snippets/lists/aggregation-functions.md index 8dcef115334d7..b4c4f1956533d 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/aggregation-functions.md +++ b/docs/reference/query-languages/esql/_snippets/lists/aggregation-functions.md @@ -2,13 +2,15 @@ * [`AVG`](../../functions-operators/aggregation-functions/avg.md) * [`COUNT`](../../functions-operators/aggregation-functions/count.md) * [`COUNT_DISTINCT`](../../functions-operators/aggregation-functions/count_distinct.md) +* [`FIRST`](../../functions-operators/aggregation-functions/first.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` +* [`LAST`](../../functions-operators/aggregation-functions/last.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` * [`MAX`](../../functions-operators/aggregation-functions/max.md) * [`MEDIAN`](../../functions-operators/aggregation-functions/median.md) * [`MEDIAN_ABSOLUTE_DEVIATION`](../../functions-operators/aggregation-functions/median_absolute_deviation.md) * [`MIN`](../../functions-operators/aggregation-functions/min.md) * [`PERCENTILE`](../../functions-operators/aggregation-functions/percentile.md) * [`PRESENT`](../../functions-operators/aggregation-functions/present.md) {applies_to}`stack: ga 9.2` -* [`SAMPLE`](../../functions-operators/aggregation-functions/sample.md) +* [`SAMPLE`](../../functions-operators/aggregation-functions/sample.md) {applies_to}`stack: ga 9.1` * [`ST_CENTROID_AGG`](../../functions-operators/aggregation-functions/st_centroid_agg.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` * [`ST_EXTENT_AGG`](../../functions-operators/aggregation-functions/st_extent_agg.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` * [`STD_DEV`](../../functions-operators/aggregation-functions/std_dev.md) @@ -17,5 +19,3 @@ * [`VALUES`](../../functions-operators/aggregation-functions/values.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` * [`VARIANCE`](../../functions-operators/aggregation-functions/variance.md) * [`WEIGHTED_AVG`](../../functions-operators/aggregation-functions/weighted_avg.md) -* [`FIRST`](../../functions-operators/aggregation-functions/first.md) -* [`LAST`](../../functions-operators/aggregation-functions/last.md) diff --git a/docs/reference/query-languages/esql/_snippets/lists/date-time-functions.md b/docs/reference/query-languages/esql/_snippets/lists/date-time-functions.md index f9d1b8bbbedf3..ded819f12e986 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/date-time-functions.md +++ b/docs/reference/query-languages/esql/_snippets/lists/date-time-functions.md @@ -3,7 +3,7 @@ * [`DATE_FORMAT`](../../functions-operators/date-time-functions/date_format.md) * [`DATE_PARSE`](../../functions-operators/date-time-functions/date_parse.md) * [`DATE_TRUNC`](../../functions-operators/date-time-functions/date_trunc.md) -* [`DAY_NAME`](../../functions-operators/date-time-functions/day_name.md) -* [`MONTH_NAME`](../../functions-operators/date-time-functions/month_name.md) +* [`DAY_NAME`](../../functions-operators/date-time-functions/day_name.md) {applies_to}`stack: ga 9.2` +* [`MONTH_NAME`](../../functions-operators/date-time-functions/month_name.md) {applies_to}`stack: ga 9.2` * [`NOW`](../../functions-operators/date-time-functions/now.md) -* [`TRANGE`](../../functions-operators/date-time-functions/trange.md) +* [`TRANGE`](../../functions-operators/date-time-functions/trange.md) {applies_to}`stack: ga 9.3` diff --git a/docs/reference/query-languages/esql/_snippets/lists/dense-vector-functions.md b/docs/reference/query-languages/esql/_snippets/lists/dense-vector-functions.md index 10ef9e319b96d..77e54aac6a08d 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/dense-vector-functions.md +++ b/docs/reference/query-languages/esql/_snippets/lists/dense-vector-functions.md @@ -1,10 +1,10 @@ * Dense vector functions - * [`KNN`](../../functions-operators/dense-vector-functions/knn.md) {applies_to}`stack: preview 9.2` {applies_to}`serverless: preview` - * [`TEXT_EMBEDDING`](../../functions-operators/dense-vector-functions/text_embedding.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` + * [`KNN`](../../functions-operators/dense-vector-functions/knn.md) {applies_to}`stack: preview 9.2` {applies_to}`stack: ga 9.4` + * [`TEXT_EMBEDDING`](../../functions-operators/dense-vector-functions/text_embedding.md) {applies_to}`stack: preview 9.3` {applies_to}`stack: ga 9.4` * Vector similarity functions - * [`V_COSINE`](../../functions-operators/dense-vector-functions/v_cosine.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` - * [`V_DOT_PRODUCT`](../../functions-operators/dense-vector-functions/v_dot_product.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` - * [`V_HAMMING`](../../functions-operators/dense-vector-functions/v_hamming.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` - * [`V_L1_NORM`](../../functions-operators/dense-vector-functions/v_l1_norm.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` - * [`V_L2_NORM`](../../functions-operators/dense-vector-functions/v_l2_norm.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` + * [`V_COSINE`](../../functions-operators/dense-vector-functions/v_cosine.md) {applies_to}`stack: preview 9.3` {applies_to}`stack: ga 9.4` + * [`V_DOT_PRODUCT`](../../functions-operators/dense-vector-functions/v_dot_product.md) {applies_to}`stack: preview 9.3` {applies_to}`stack: ga 9.4` + * [`V_HAMMING`](../../functions-operators/dense-vector-functions/v_hamming.md) {applies_to}`stack: preview 9.3` {applies_to}`stack: ga 9.4` + * [`V_L1_NORM`](../../functions-operators/dense-vector-functions/v_l1_norm.md) {applies_to}`stack: preview 9.3` {applies_to}`stack: ga 9.4` + * [`V_L2_NORM`](../../functions-operators/dense-vector-functions/v_l2_norm.md) {applies_to}`stack: preview 9.3` {applies_to}`stack: ga 9.4` % * [`V_MAGNITUDE`](../../functions-operators/dense-vector-functions/v_magnitude.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` diff --git a/docs/reference/query-languages/esql/_snippets/lists/grouping-functions.md b/docs/reference/query-languages/esql/_snippets/lists/grouping-functions.md index ee3896a37f4f4..17d3890b895df 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/grouping-functions.md +++ b/docs/reference/query-languages/esql/_snippets/lists/grouping-functions.md @@ -1,3 +1,3 @@ * [`BUCKET`](../../functions-operators/grouping-functions/bucket.md) -* [`TBUCKET`](../../functions-operators/grouping-functions/tbucket.md) -* [`CATEGORIZE`](../../functions-operators/grouping-functions/categorize.md) +* [`CATEGORIZE`](../../functions-operators/grouping-functions/categorize.md) {applies_to}`stack: preview 9.0` {applies_to}`stack: ga 9.1` +* [`TBUCKET`](../../functions-operators/grouping-functions/tbucket.md) {applies_to}`stack: ga 9.2` diff --git a/docs/reference/query-languages/esql/_snippets/lists/math-functions.md b/docs/reference/query-languages/esql/_snippets/lists/math-functions.md index a7ab86264ddf8..f62de3099d3b5 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/math-functions.md +++ b/docs/reference/query-languages/esql/_snippets/lists/math-functions.md @@ -8,7 +8,7 @@ * [`ATANH`](../../functions-operators/math-functions/atanh.md) * [`CBRT`](../../functions-operators/math-functions/cbrt.md) * [`CEIL`](../../functions-operators/math-functions/ceil.md) -* [`COPY_SIGN`](../../functions-operators/math-functions/copy_sign.md) +* [`COPY_SIGN`](../../functions-operators/math-functions/copy_sign.md) {applies_to}`stack: ga 9.1` * [`COS`](../../functions-operators/math-functions/cos.md) * [`COSH`](../../functions-operators/math-functions/cosh.md) * [`E`](../../functions-operators/math-functions/e.md) @@ -20,8 +20,8 @@ * [`PI`](../../functions-operators/math-functions/pi.md) * [`POW`](../../functions-operators/math-functions/pow.md) * [`ROUND`](../../functions-operators/math-functions/round.md) -* [`ROUND_TO`](../../functions-operators/math-functions/round_to.md) -* [`SCALB`](../../functions-operators/math-functions/scalb.md) +* [`ROUND_TO`](../../functions-operators/math-functions/round_to.md) {applies_to}`stack: preview 9.1` {applies_to}`serverless: preview` +* [`SCALB`](../../functions-operators/math-functions/scalb.md) {applies_to}`stack: ga 9.1` * [`SIGNUM`](../../functions-operators/math-functions/signum.md) * [`SIN`](../../functions-operators/math-functions/sin.md) * [`SINH`](../../functions-operators/math-functions/sinh.md) diff --git a/docs/reference/query-languages/esql/_snippets/lists/mv-functions.md b/docs/reference/query-languages/esql/_snippets/lists/mv-functions.md index 9a92b11e91aad..24cfb9580eb1f 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/mv-functions.md +++ b/docs/reference/query-languages/esql/_snippets/lists/mv-functions.md @@ -1,12 +1,12 @@ * [`MV_APPEND`](../../functions-operators/mv-functions/mv_append.md) * [`MV_AVG`](../../functions-operators/mv-functions/mv_avg.md) * [`MV_CONCAT`](../../functions-operators/mv-functions/mv_concat.md) -* [`MV_CONTAINS`](../../functions-operators/mv-functions/mv_contains.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` +* [`MV_CONTAINS`](../../functions-operators/mv-functions/mv_contains.md) {applies_to}`stack: preview 9.2` {applies_to}`serverless: preview` * [`MV_COUNT`](../../functions-operators/mv-functions/mv_count.md) * [`MV_DEDUPE`](../../functions-operators/mv-functions/mv_dedupe.md) * [`MV_FIRST`](../../functions-operators/mv-functions/mv_first.md) * [`MV_INTERSECTION`](../../functions-operators/mv-functions/mv_intersection.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` -* [`MV_INTERSECTS`](../../functions-operators/mv-functions/mv_intersects.md) {applies_to}`stack: preview 9.4` {applies_to}`serverless: preview` +* [`MV_INTERSECTS`](../../functions-operators/mv-functions/mv_intersects.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` * [`MV_LAST`](../../functions-operators/mv-functions/mv_last.md) * [`MV_MAX`](../../functions-operators/mv-functions/mv_max.md) * [`MV_MEDIAN`](../../functions-operators/mv-functions/mv_median.md) diff --git a/docs/reference/query-languages/esql/_snippets/lists/processing-commands.md b/docs/reference/query-languages/esql/_snippets/lists/processing-commands.md index 499b2ef849d2e..675d348031c23 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/processing-commands.md +++ b/docs/reference/query-languages/esql/_snippets/lists/processing-commands.md @@ -1,21 +1,21 @@ -* [`CHANGE_POINT`](/reference/query-languages/esql/commands/change-point.md) -* [`COMPLETION`](/reference/query-languages/esql/commands/completion.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` +* [`CHANGE_POINT`](/reference/query-languages/esql/commands/change-point.md) {applies_to}`stack: preview 9.1` {applies_to}`stack: ga 9.2` +* [`COMPLETION`](/reference/query-languages/esql/commands/completion.md) {applies_to}`stack: preview 9.1` {applies_to}`stack: ga 9.3` * [`DISSECT`](/reference/query-languages/esql/commands/dissect.md) * [`DROP`](/reference/query-languages/esql/commands/drop.md) * [`ENRICH`](/reference/query-languages/esql/commands/enrich.md) * [`EVAL`](/reference/query-languages/esql/commands/eval.md) * [`GROK`](/reference/query-languages/esql/commands/grok.md) -* [`FORK`](/reference/query-languages/esql/commands/fork.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` -* [`FUSE`](/reference/query-languages/esql/commands/fuse.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` +* [`FORK`](/reference/query-languages/esql/commands/fork.md) {applies_to}`stack: preview 9.1` {applies_to}`serverless: preview` +* [`FUSE`](/reference/query-languages/esql/commands/fuse.md) {applies_to}`stack: preview 9.2` {applies_to}`serverless: preview` * [`KEEP`](/reference/query-languages/esql/commands/keep.md) * [`LIMIT`](/reference/query-languages/esql/commands/limit.md) -* [`LOOKUP JOIN`](/reference/query-languages/esql/commands/lookup-join.md) -* [`INLINE STATS`](/reference/query-languages/esql/commands/inlinestats-by.md) +* [`LOOKUP JOIN`](/reference/query-languages/esql/commands/lookup-join.md) {applies_to}`stack: preview 9.0` {applies_to}`stack: ga 9.1` +* [`INLINE STATS`](/reference/query-languages/esql/commands/inlinestats-by.md) {applies_to}`stack: preview 9.2` {applies_to}`stack: ga 9.3` * [`MV_EXPAND`](/reference/query-languages/esql/commands/mv_expand.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` % * [`REGISTERED_DOMAIN`](/reference/query-languages/esql/commands/registered-domain.md) {applies_to}`stack: preview 9.4` {applies_to}`serverless: preview` * [`RENAME`](/reference/query-languages/esql/commands/rename.md) -* [`RERANK`](/reference/query-languages/esql/commands/rerank.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` -* [`SAMPLE`](/reference/query-languages/esql/commands/sample.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` +* [`RERANK`](/reference/query-languages/esql/commands/rerank.md) {applies_to}`stack: preview 9.2` {applies_to}`stack: ga 9.4` +* [`SAMPLE`](/reference/query-languages/esql/commands/sample.md) {applies_to}`stack: preview 9.1` {applies_to}`serverless: preview` * [`SORT`](/reference/query-languages/esql/commands/sort.md) * [`STATS`](/reference/query-languages/esql/commands/stats-by.md) % * [`URI_PARTS`](/reference/query-languages/esql/commands/uri-parts.md) {applies_to}`stack: preview 9.4` {applies_to}`serverless: preview` diff --git a/docs/reference/query-languages/esql/_snippets/lists/search-functions.md b/docs/reference/query-languages/esql/_snippets/lists/search-functions.md index a00ac649ff22a..47ceed8666ceb 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/search-functions.md +++ b/docs/reference/query-languages/esql/_snippets/lists/search-functions.md @@ -1,8 +1,8 @@ -* [`DECAY`](../../functions-operators/search-functions/decay.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` -* [`KQL`](../../functions-operators/search-functions/kql.md) -* [`MATCH`](../../functions-operators/search-functions/match.md) -* [`MATCH_PHRASE`](../../functions-operators/search-functions/match_phrase.md) -* [`QSTR`](../../functions-operators/search-functions/qstr.md) -* [`SCORE`](../../functions-operators/search-functions/score.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` +* [`DECAY`](../../functions-operators/search-functions/decay.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` +* [`KQL`](../../functions-operators/search-functions/kql.md) {applies_to}`stack: preview 9.0` {applies_to}`stack: ga 9.1` +* [`MATCH`](../../functions-operators/search-functions/match.md) {applies_to}`stack: preview 9.0` {applies_to}`stack: ga 9.1` +* [`MATCH_PHRASE`](../../functions-operators/search-functions/match_phrase.md) {applies_to}`stack: ga 9.1` +* [`QSTR`](../../functions-operators/search-functions/qstr.md) {applies_to}`stack: preview 9.0` {applies_to}`stack: ga 9.1` +* [`SCORE`](../../functions-operators/search-functions/score.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` % * [`TERM`](../../functions-operators/search-functions/term.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` -* [`TOP_SNIPPETS`](../../functions-operators/search-functions/top-snippets.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` +* [`TOP_SNIPPETS`](../../functions-operators/search-functions/top-snippets.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` diff --git a/docs/reference/query-languages/esql/_snippets/lists/source-commands.md b/docs/reference/query-languages/esql/_snippets/lists/source-commands.md index 3b806f15255fc..e3f10aee28c23 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/source-commands.md +++ b/docs/reference/query-languages/esql/_snippets/lists/source-commands.md @@ -1,4 +1,4 @@ - [`FROM`](/reference/query-languages/esql/commands/from.md) - [`ROW`](/reference/query-languages/esql/commands/row.md) - [`SHOW`](/reference/query-languages/esql/commands/show.md) -- [`TS`](/reference/query-languages/esql/commands/ts.md) +- [`TS`](/reference/query-languages/esql/commands/ts.md) {applies_to}`stack: preview 9.2` {applies_to}`serverless: preview` diff --git a/docs/reference/query-languages/esql/_snippets/lists/string-functions.md b/docs/reference/query-languages/esql/_snippets/lists/string-functions.md index dcfe524b6244e..1023c408daec2 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/string-functions.md +++ b/docs/reference/query-languages/esql/_snippets/lists/string-functions.md @@ -1,12 +1,12 @@ * [`BIT_LENGTH`](../../functions-operators/string-functions/bit_length.md) * [`BYTE_LENGTH`](../../functions-operators/string-functions/byte_length.md) -* [`CHUNK`](../../functions-operators/string-functions/chunk.md) +* [`CHUNK`](../../functions-operators/string-functions/chunk.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` * [`CONCAT`](../../functions-operators/string-functions/concat.md) -* [`CONTAINS`](../../functions-operators/string-functions/contains.md) +* [`CONTAINS`](../../functions-operators/string-functions/contains.md) {applies_to}`stack: ga 9.2` * [`ENDS_WITH`](../../functions-operators/string-functions/ends_with.md) * [`FROM_BASE64`](../../functions-operators/string-functions/from_base64.md) * [`HASH`](../../functions-operators/string-functions/hash.md) -* [`JSON_EXTRACT`](../../functions-operators/string-functions/json_extract.md) +* [`JSON_EXTRACT`](../../functions-operators/string-functions/json_extract.md) {applies_to}`stack: preview 9.4` {applies_to}`serverless: preview` * [`LEFT`](../../functions-operators/string-functions/left.md) * [`LENGTH`](../../functions-operators/string-functions/length.md) * [`LOCATE`](../../functions-operators/string-functions/locate.md) @@ -27,6 +27,6 @@ * [`TO_LOWER`](../../functions-operators/string-functions/to_lower.md) * [`TO_UPPER`](../../functions-operators/string-functions/to_upper.md) * [`TRIM`](../../functions-operators/string-functions/trim.md) -* [`URL_ENCODE`](../../functions-operators/string-functions/url_encode.md) -* [`URL_ENCODE_COMPONENT`](../../functions-operators/string-functions/url_encode_component.md) -* [`URL_DECODE`](../../functions-operators/string-functions/url_decode.md) +* [`URL_DECODE`](../../functions-operators/string-functions/url_decode.md) {applies_to}`stack: ga 9.2` +* [`URL_ENCODE`](../../functions-operators/string-functions/url_encode.md) {applies_to}`stack: ga 9.2` +* [`URL_ENCODE_COMPONENT`](../../functions-operators/string-functions/url_encode_component.md) {applies_to}`stack: ga 9.2` diff --git a/docs/reference/query-languages/esql/_snippets/lists/time-series-aggregation-functions.md b/docs/reference/query-languages/esql/_snippets/lists/time-series-aggregation-functions.md index 53ca41fa689a6..657fcaf17b7b0 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/time-series-aggregation-functions.md +++ b/docs/reference/query-languages/esql/_snippets/lists/time-series-aggregation-functions.md @@ -11,7 +11,7 @@ * [`LAST_OVER_TIME`](../../functions-operators/time-series-aggregation-functions/last_over_time.md) {applies_to}`stack: preview 9.2` {applies_to}`serverless: preview` * [`MAX_OVER_TIME`](../../functions-operators/time-series-aggregation-functions/max_over_time.md) {applies_to}`stack: preview 9.2` {applies_to}`serverless: preview` * [`MIN_OVER_TIME`](../../functions-operators/time-series-aggregation-functions/min_over_time.md) {applies_to}`stack: preview 9.2` {applies_to}`serverless: preview` -* [`PERCENTILE_OVER_TIME`](../../functions-operators/time-series-aggregation-functions/percentile_over_time.md) {applies_to}`stack: preview 9.2` {applies_to}`serverless: preview` +* [`PERCENTILE_OVER_TIME`](../../functions-operators/time-series-aggregation-functions/percentile_over_time.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` * [`PRESENT_OVER_TIME`](../../functions-operators/time-series-aggregation-functions/present_over_time.md) {applies_to}`stack: preview 9.2` {applies_to}`serverless: preview` * [`RATE`](../../functions-operators/time-series-aggregation-functions/rate.md) {applies_to}`stack: preview 9.2` {applies_to}`serverless: preview` * [`STDDEV_OVER_TIME`](../../functions-operators/time-series-aggregation-functions/stddev_over_time.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` diff --git a/docs/reference/query-languages/esql/_snippets/lists/type-conversion-functions.md b/docs/reference/query-languages/esql/_snippets/lists/type-conversion-functions.md index 1aba71a983c45..42d8b262110cc 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/type-conversion-functions.md +++ b/docs/reference/query-languages/esql/_snippets/lists/type-conversion-functions.md @@ -18,7 +18,7 @@ * [`TO_LONG`](../../functions-operators/type-conversion-functions/to_long.md) * [`TO_RADIANS`](../../functions-operators/type-conversion-functions/to_radians.md) * [`TO_STRING`](../../functions-operators/type-conversion-functions/to_string.md) -* [`TO_TDIGEST`](../../functions-operators/type-conversion-functions/to_tdigest.md) +* [`TO_TDIGEST`](../../functions-operators/type-conversion-functions/to_tdigest.md) {applies_to}`stack: preview 9.3` {applies_to}`serverless: preview` * [`TO_TIMEDURATION`](../../functions-operators/type-conversion-functions/to_timeduration.md) * [`TO_UNSIGNED_LONG`](../../functions-operators/type-conversion-functions/to_unsigned_long.md) {applies_to}`stack: preview` {applies_to}`serverless: preview` * [`TO_VERSION`](../../functions-operators/type-conversion-functions/to_version.md) diff --git a/docs/reference/query-languages/esql/functions-operators/time-series-aggregation-functions.md b/docs/reference/query-languages/esql/functions-operators/time-series-aggregation-functions.md index f3ef650f24030..56332614595c1 100644 --- a/docs/reference/query-languages/esql/functions-operators/time-series-aggregation-functions.md +++ b/docs/reference/query-languages/esql/functions-operators/time-series-aggregation-functions.md @@ -1,4 +1,7 @@ --- +applies_to: + stack: ga + serverless: ga navigation_title: "Time series aggregation functions" mapped_pages: - https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-functions-operators.html#esql-time-series-agg-functions From 48ed46212398438bdd748f0f9758ddc815822df6 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine <58790826+elasticsearchmachine@users.noreply.github.com> Date: Tue, 3 Mar 2026 14:55:14 +0100 Subject: [PATCH 063/137] Mute org.elasticsearch.compute.lucene.read.ValueSourceReaderTypeConversionTests testLoadAll #143471 --- muted-tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/muted-tests.yml b/muted-tests.yml index ce0c2a16965ef..578725c650550 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -456,6 +456,9 @@ tests: - class: org.elasticsearch.xpack.esql.CsvIT method: test {csv-spec:lookup-join.LookupJoinWithCoalesceFilterOnRight} issue: https://github.com/elastic/elasticsearch/issues/143443 +- class: org.elasticsearch.compute.lucene.read.ValueSourceReaderTypeConversionTests + method: testLoadAll + issue: https://github.com/elastic/elasticsearch/issues/143471 # Examples: # From 05862b98c829091e6f0803f981d2d022623d328c Mon Sep 17 00:00:00 2001 From: Pat Whelan Date: Tue, 3 Mar 2026 09:53:30 -0500 Subject: [PATCH 064/137] [Transform] Stop transforms at the end of tests (#139783) Stopping the transform at the end of test, before the reset, can help other tests running in parallel. Resolve #122980 --- .../xpack/transform/integration/TransformUpdateIT.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/x-pack/plugin/transform/qa/single-node-tests/src/javaRestTest/java/org/elasticsearch/xpack/transform/integration/TransformUpdateIT.java b/x-pack/plugin/transform/qa/single-node-tests/src/javaRestTest/java/org/elasticsearch/xpack/transform/integration/TransformUpdateIT.java index ec0275789ec85..e91dc328176cc 100644 --- a/x-pack/plugin/transform/qa/single-node-tests/src/javaRestTest/java/org/elasticsearch/xpack/transform/integration/TransformUpdateIT.java +++ b/x-pack/plugin/transform/qa/single-node-tests/src/javaRestTest/java/org/elasticsearch/xpack/transform/integration/TransformUpdateIT.java @@ -364,6 +364,11 @@ private void updateTransferRightsTester(boolean useSecondaryAuthHeaders) throws Map transformStatsAsMap = getTransformStateAndStats(transformIdCloned); assertThat(XContentMapValues.extractValue("stats.documents_indexed", transformStatsAsMap), equalTo(27)); }, 15, TimeUnit.SECONDS); + + stopTransform(transformId, BASIC_AUTH_VALUE_TRANSFORM_ADMIN_1, true, false); + stopTransform(transformIdCloned, BASIC_AUTH_VALUE_TRANSFORM_ADMIN_1, true, false); + deleteTransform(transformId); + deleteTransform(transformIdCloned); } private void deleteUser(String user) throws IOException { From f20aca7c0f9343d38493d190e2850f233e8007b0 Mon Sep 17 00:00:00 2001 From: Parker Timmins Date: Tue, 3 Mar 2026 09:03:35 -0600 Subject: [PATCH 065/137] Improve pattern text downgrade license test (#143102) Update the pattern_text downgrade test so that it includes adding docs and querying for docs.\ Specifically the test now does the following: 1. Create data stream with trial license and pattern text field 2. Index docs, verify they're searchable. 3. Downgrade to basic license. 4. Index more docs in same backing index, verify all docs searchable, verify settings unchanged. 5. Rollover the data stream, verify the new backing index has disable_templating=true. 6. Index more docs into the new backing index, verify all docs searchable across both indices. 7. Search with "fields": ["pattern_field"] to verify the valueFetcher() code path works across both backing indices. --- .../PatternTextLicenseDowngradeIT.java | 100 +++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/patterntext/PatternTextLicenseDowngradeIT.java b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/patterntext/PatternTextLicenseDowngradeIT.java index e6f8ec12075d7..04f4f4847d4a0 100644 --- a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/patterntext/PatternTextLicenseDowngradeIT.java +++ b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/patterntext/PatternTextLicenseDowngradeIT.java @@ -7,14 +7,23 @@ package org.elasticsearch.xpack.logsdb.patterntext; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.Response; +import org.elasticsearch.test.rest.ObjectPath; import org.elasticsearch.xpack.logsdb.DataStreamLicenseChangeTestCase; import org.junit.Before; import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Set; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.hasKey; +import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; public class PatternTextLicenseDowngradeIT extends DataStreamLicenseChangeTestCase { @@ -54,9 +63,25 @@ public void testLicenseDowngrade() throws IOException { assertThat(patternFieldMapping, not(hasKey("disable_templating"))); } + // Index docs while on trial license (templating enabled) + List preDowngradeDocs = List.of("foo 123 bar", "baz 456 qux", "hello 789 world"); + indexDocs(dataStreamName, preDowngradeDocs); + + // Verify search returns pre-downgrade docs + assertSearchReturnsValues(preDowngradeDocs); + startBasic(); - rolloverDataStream(client(), dataStreamName); + // Index docs after downgrade into the same backing index (still has disable_templating=false) + List postDowngradeDocs = List.of("post downgrade 111", "another post 222"); + indexDocs(dataStreamName, postDowngradeDocs); + + // Verify search returns all docs from before and after downgrade + List allDocsBeforeRollover = new ArrayList<>(preDowngradeDocs); + allDocsBeforeRollover.addAll(postDowngradeDocs); + assertSearchReturnsValues(allDocsBeforeRollover); + + // Original backing index settings remain unchanged after downgrade { assertEquals("false", getSetting(client(), backingIndex0, "index.mapping.pattern_text.disable_templating")); Map mapping = getMapping(client(), backingIndex0); @@ -66,6 +91,8 @@ public void testLicenseDowngrade() throws IOException { assertThat(patternFieldMapping, not(hasKey("disable_templating"))); } + rolloverDataStream(client(), dataStreamName); + String backingIndex1 = getDataStreamBackingIndex(client(), dataStreamName, 1); { assertEquals("true", getSetting(client(), backingIndex1, "index.mapping.pattern_text.disable_templating")); @@ -76,5 +103,76 @@ public void testLicenseDowngrade() throws IOException { assertThat(patternFieldMapping, hasEntry("disable_templating", true)); } + // Index docs into the new (downgraded) backing index + List postRolloverDocs = List.of("rolled over 333", "new index 444", "downgraded 555"); + indexDocs(dataStreamName, postRolloverDocs); + + // Verify search across all backing indices returns every doc + List allDocs = new ArrayList<>(allDocsBeforeRollover); + allDocs.addAll(postRolloverDocs); + assertSearchReturnsValues(allDocs); + + // Fetch pattern_field via the "fields" parameter, which exercises the valueFetcher() code path. + // With disabled templating, valueFetcher must load values from binary doc values or stored fields + // rather than from pattern_text template+args doc values. + assertFieldsFetchReturnsValues(allDocs); + } + + private static void indexDocs(String dataStreamName, List values) throws IOException { + StringBuilder sb = new StringBuilder(); + for (String value : values) { + sb.append("{\"create\": {}}\n"); + sb.append("{\"pattern_field\": \"").append(value).append("\"}\n"); + } + assertOK(bulkIndex(client(), dataStreamName, sb::toString)); + } + + @SuppressWarnings("unchecked") + private static void assertSearchReturnsValues(List expectedValues) throws IOException { + Request searchRequest = new Request("GET", "/" + "logs-test-pattern-text" + "/_search"); + searchRequest.setJsonEntity(""" + { + "query": {"match_all": {}}, + "size": 100 + } + """); + Response response = client().performRequest(searchRequest); + assertThat(response.getStatusLine().getStatusCode(), is(200)); + ObjectPath objectPath = ObjectPath.createFromResponse(response); + + assertThat(objectPath.evaluate("hits.total.value"), equalTo(expectedValues.size())); + List> hits = objectPath.evaluate("hits.hits"); + Set actual = new HashSet<>(); + for (Map hit : hits) { + Map source = (Map) hit.get("_source"); + actual.add((String) source.get("pattern_field")); + } + assertEquals(new HashSet<>(expectedValues), actual); + } + + @SuppressWarnings("unchecked") + private static void assertFieldsFetchReturnsValues(List expectedValues) throws IOException { + Request searchRequest = new Request("GET", "/" + "logs-test-pattern-text" + "/_search"); + searchRequest.setJsonEntity(""" + { + "query": {"match_all": {}}, + "fields": ["pattern_field"], + "size": 100 + } + """); + Response response = client().performRequest(searchRequest); + assertThat(response.getStatusLine().getStatusCode(), is(200)); + ObjectPath objectPath = ObjectPath.createFromResponse(response); + + assertThat(objectPath.evaluate("hits.total.value"), equalTo(expectedValues.size())); + List> hits = objectPath.evaluate("hits.hits"); + Set actual = new HashSet<>(); + for (Map hit : hits) { + Map fields = (Map) hit.get("fields"); + List values = (List) fields.get("pattern_field"); + assertThat(values.size(), equalTo(1)); + actual.add(values.get(0)); + } + assertEquals(new HashSet<>(expectedValues), actual); } } From a2b004e5358bc2e023d133eddaaf90387e07cccf Mon Sep 17 00:00:00 2001 From: Tanguy Leroux Date: Tue, 3 Mar 2026 16:11:51 +0100 Subject: [PATCH 066/137] [Test] Randomly disable doc values skippers in time-series indices (#143389) This change disables index.mapping.use_doc_values_skipper in about 10% of tests executions of the main TSDB with synthetic id tests, as well as in some unit tests. It also makes the necessary changes in the postings format to account for missing doc values skippers. Relates ES-14224 --- .../datastreams/TSDBSyntheticIdsIT.java | 3 + .../tsdb/TSDBSyntheticIdDocValuesHolder.java | 13 ++++ .../tsdb/TSDBSyntheticIdFieldsProducer.java | 62 ++++++++++--------- .../TSDBSyntheticIdPostingsFormatTests.java | 53 +++++++--------- 4 files changed, 73 insertions(+), 58 deletions(-) diff --git a/modules/data-streams/src/internalClusterTest/java/org/elasticsearch/datastreams/TSDBSyntheticIdsIT.java b/modules/data-streams/src/internalClusterTest/java/org/elasticsearch/datastreams/TSDBSyntheticIdsIT.java index c97589c5ab93d..9d98267009832 100644 --- a/modules/data-streams/src/internalClusterTest/java/org/elasticsearch/datastreams/TSDBSyntheticIdsIT.java +++ b/modules/data-streams/src/internalClusterTest/java/org/elasticsearch/datastreams/TSDBSyntheticIdsIT.java @@ -1221,6 +1221,9 @@ private static void putDataStreamTemplate(String indexPattern, int primaries, in } else if (rarely()) { settings.put(IndexSettings.INDEX_MAPPER_SOURCE_MODE_SETTING.getKey(), SourceFieldMapper.Mode.STORED); } + if (rarely()) { + settings.put(IndexSettings.USE_DOC_VALUES_SKIPPER.getKey(), false); + } settings.put(extraSettings); final var mappings = """ diff --git a/server/src/main/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdDocValuesHolder.java b/server/src/main/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdDocValuesHolder.java index e1e289b94efdc..ce3ea494b8960 100644 --- a/server/src/main/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdDocValuesHolder.java +++ b/server/src/main/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdDocValuesHolder.java @@ -10,6 +10,7 @@ package org.elasticsearch.index.codec.tsdb; import org.apache.lucene.codecs.DocValuesProducer; +import org.apache.lucene.index.DocValuesSkipIndexType; import org.apache.lucene.index.DocValuesSkipper; import org.apache.lucene.index.FieldInfo; import org.apache.lucene.index.FieldInfos; @@ -17,6 +18,7 @@ import org.apache.lucene.index.SortedNumericDocValues; import org.apache.lucene.search.DocIdSetIterator; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.core.Nullable; import org.elasticsearch.index.mapper.TimeSeriesRoutingHashFieldMapper; import org.elasticsearch.index.mapper.TsidExtractingIdFieldMapper; import org.elasticsearch.index.mapper.Uid; @@ -39,6 +41,8 @@ class TSDBSyntheticIdDocValuesHolder { private final FieldInfo timestampFieldInfo; private final FieldInfo routingHashFieldInfo; private final DocValuesProducer docValuesProducer; + private final boolean hasTsIdSkipper; + private final boolean hasTimestampSkipper; private SortedNumericDocValues timestampDocValues; // sorted desc. order private SortedDocValues routingHashDocValues; // sorted asc. order @@ -52,6 +56,8 @@ class TSDBSyntheticIdDocValuesHolder { this.timestampFieldInfo = safeFieldInfo(fieldInfos, TSDBSyntheticIdPostingsFormat.TIMESTAMP); this.routingHashFieldInfo = safeFieldInfo(fieldInfos, TSDBSyntheticIdPostingsFormat.TS_ROUTING_HASH); this.docValuesProducer = docValuesProducer; + this.hasTsIdSkipper = tsIdFieldInfo.docValuesSkipIndexType() != DocValuesSkipIndexType.NONE; + this.hasTimestampSkipper = timestampFieldInfo.docValuesSkipIndexType() != DocValuesSkipIndexType.NONE; } private FieldInfo safeFieldInfo(FieldInfos fieldInfos, String fieldName) { @@ -178,6 +184,9 @@ BytesRef lookupTsIdOrd(int tsIdOrdinal) throws IOException { * @throws IOException if any I/O exception occurs */ private int findStartDocIDForTsIdOrd(int tsIdOrd) throws IOException { + if (hasTsIdSkipper == false) { + return 0; + } var skipper = docValuesProducer.getSkipper(tsIdFieldInfo); assert skipper != null; if (skipper.minValue() > tsIdOrd || tsIdOrd > skipper.maxValue()) { @@ -265,7 +274,11 @@ int findFirstDocWithTsIdOrdinalEqualTo(int tsIdOrd) throws IOException { return DocIdSetIterator.NO_MORE_DOCS; } + @Nullable DocValuesSkipper docValuesSkipperForTimestamp() throws IOException { + if (hasTimestampSkipper == false) { + return null; + } var skipper = docValuesProducer.getSkipper(timestampFieldInfo); assert skipper != null; return skipper; diff --git a/server/src/main/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdFieldsProducer.java b/server/src/main/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdFieldsProducer.java index 5cd8771f5ee8f..c4ea2553283b3 100644 --- a/server/src/main/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdFieldsProducer.java +++ b/server/src/main/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdFieldsProducer.java @@ -232,40 +232,44 @@ public SeekStatus seekCeil(BytesRef id) throws IOException { final long timestamp = TsidExtractingIdFieldMapper.extractTimestampFromSyntheticId(id); // Use doc values skipper on timestamp to early exit or skip to the first document matching the timestamp + int nextDocID; var skipper = docValues.docValuesSkipperForTimestamp(); - if (timestamp > skipper.maxValue()) { - // timestamp is greater than the global maximum value in the segment, so the first docID matching the _tsid is guaranteed to - // have a smaller timestamp that the one we're looking for and we can early exit at the current docID position. Note that - // synthetic ids are generated so that the resulting array of bytes has a natural order that reflects the order of docs in - // the segment (_tsid asc then @timestamp desc). So if timestamp > skipper.maxValue(), it means that the next doc has a - // @timestamp smaller than what we're looking for. - docID = firstDocID; - docTsIdOrd = tsIdOrd; - docTimestamp = null; - return SeekStatus.NOT_FOUND; - } - if (skipper.minValue() > timestamp) { - // timestamp is smaller than the global minimum value in the segment, so no docs matching the _tsid will also match the - // timestamp, so we can early exit at the position of the next _tsid (if there is such one). - int nextDocTsIdOrd = tsIdOrd + 1; - if (nextDocTsIdOrd < docValues.getTsIdValueCount()) { - docID = docValues.findFirstDocWithTsIdOrdinalEqualTo(nextDocTsIdOrd); - docTsIdOrd = nextDocTsIdOrd; + if (skipper != null) { + if (timestamp > skipper.maxValue()) { + // timestamp is greater than the global maximum value in the segment, so the first docID matching the _tsid is + // guaranteed to have a smaller timestamp that the one we're looking for and we can early exit at the current docID + // position. Note that synthetic ids are generated so that the resulting array of bytes has a natural order that + // reflects the order of docs in the segment (_tsid asc then @timestamp desc). So if timestamp > skipper.maxValue(), + // it means that the next doc has a @timestamp smaller than what we're looking for. + docID = firstDocID; + docTsIdOrd = tsIdOrd; docTimestamp = null; return SeekStatus.NOT_FOUND; } - // no docs/terms to iterate on - resetDocID(DocIdSetIterator.NO_MORE_DOCS); - return SeekStatus.END; - } - skipper.advance(firstDocID); - skipper.advance(timestamp, Long.MAX_VALUE); - - int nextDocID; - if (skipper.minDocID(0) != DocIdSetIterator.NO_MORE_DOCS) { - nextDocID = Math.max(firstDocID, skipper.minDocID(0)); + if (skipper.minValue() > timestamp) { + // timestamp is smaller than the global minimum value in the segment, so no docs matching the _tsid will also match + // the timestamp, so we can early exit at the position of the next _tsid (if there is such one). + int nextDocTsIdOrd = tsIdOrd + 1; + if (nextDocTsIdOrd < docValues.getTsIdValueCount()) { + docID = docValues.findFirstDocWithTsIdOrdinalEqualTo(nextDocTsIdOrd); + docTsIdOrd = nextDocTsIdOrd; + docTimestamp = null; + return SeekStatus.NOT_FOUND; + } + // no docs/terms to iterate on + resetDocID(DocIdSetIterator.NO_MORE_DOCS); + return SeekStatus.END; + } + skipper.advance(firstDocID); + skipper.advance(timestamp, Long.MAX_VALUE); + + if (skipper.minDocID(0) != DocIdSetIterator.NO_MORE_DOCS) { + nextDocID = Math.max(firstDocID, skipper.minDocID(0)); + } else { + // we exhausted the doc values skipper, scan all docs from first doc matching _tsid + nextDocID = firstDocID; + } } else { - // we exhausted the doc values skipper, scan all docs from first doc matching _tsid nextDocID = firstDocID; } int nextDocTsIdOrd = tsIdOrd; diff --git a/server/src/test/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdPostingsFormatTests.java b/server/src/test/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdPostingsFormatTests.java index b95cc8648cf0b..bba3b4591e143 100644 --- a/server/src/test/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdPostingsFormatTests.java +++ b/server/src/test/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdPostingsFormatTests.java @@ -503,41 +503,36 @@ private static void runTest(CheckedBiConsumer Date: Tue, 3 Mar 2026 16:16:33 +0100 Subject: [PATCH 067/137] ES|QL: Add note of future removal of FORK implicit LIMIT (#143457) --- .../esql/_snippets/commands/layout/fork.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/reference/query-languages/esql/_snippets/commands/layout/fork.md b/docs/reference/query-languages/esql/_snippets/commands/layout/fork.md index 33a88db493140..381e8b4d84fea 100644 --- a/docs/reference/query-languages/esql/_snippets/commands/layout/fork.md +++ b/docs/reference/query-languages/esql/_snippets/commands/layout/fork.md @@ -19,8 +19,16 @@ on the same input data and combines the results in a single output table. A disc Together with the [`FUSE`](/reference/query-languages/esql/commands/fuse.md) command, `FORK` enables hybrid search to combine and score results from multiple queries. To learn more about using {{esql}} for search, refer to [ES|QL for search](docs-content://solutions/search/esql-for-search.md). + +% Use applies-switch tabs once we remove the implicit limit. + ::::{note} + `FORK` branches default to `LIMIT 1000` if no `LIMIT` is provided. +In a future release, no implicit `LIMIT` will be added to `FORK` branches. +To maintain the current behavior of the queries using `FORK`, it is recommended +to include a `LIMIT` in each `FORK` branch. + :::: ## Output behavior From 641096eb1bd6651396a95e3b013dbc935a11ef7c Mon Sep 17 00:00:00 2001 From: Luigi Dell'Aquila Date: Tue, 3 Mar 2026 16:16:53 +0100 Subject: [PATCH 068/137] SQL: fix CLI tests (#143451) --- muted-tests.yml | 3 --- .../org/elasticsearch/xpack/sql/qa/security/CliApiKeyIT.java | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/muted-tests.yml b/muted-tests.yml index 578725c650550..7cc292657122d 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -366,9 +366,6 @@ tests: - class: org.elasticsearch.reindex.management.ReindexManagementClientYamlTestSuiteIT method: test {yaml=reindex/30_cancel_reindex/Cancel running reindex returns response and GET confirms completed} issue: https://github.com/elastic/elasticsearch/issues/142079 -- class: org.elasticsearch.xpack.sql.qa.security.CliApiKeyIT - method: testCliConnectionWithApiKey - issue: https://github.com/elastic/elasticsearch/issues/143125 - class: org.elasticsearch.packaging.test.DebMetadataTests method: test05CheckLintian issue: https://github.com/elastic/elasticsearch/issues/142819 diff --git a/x-pack/plugin/sql/qa/server/security/src/test/java/org/elasticsearch/xpack/sql/qa/security/CliApiKeyIT.java b/x-pack/plugin/sql/qa/server/security/src/test/java/org/elasticsearch/xpack/sql/qa/security/CliApiKeyIT.java index ff9c04e87e76c..881bf8d1a9d3c 100644 --- a/x-pack/plugin/sql/qa/server/security/src/test/java/org/elasticsearch/xpack/sql/qa/security/CliApiKeyIT.java +++ b/x-pack/plugin/sql/qa/server/security/src/test/java/org/elasticsearch/xpack/sql/qa/security/CliApiKeyIT.java @@ -12,6 +12,7 @@ import static org.elasticsearch.xpack.sql.qa.security.RestSqlIT.SSL_ENABLED; import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertEquals; /** * Integration tests for CLI connections using API key authentication. @@ -65,6 +66,7 @@ public void testCliConnectionWithApiKey() throws Exception { cli.readLine(); // separator line String valueLine = cli.readLine(); assertThat(valueLine, containsString("123")); + assertEquals("", cli.readLine()); } } From 7ca0eaa5c41ccac70a43d75241302bbabd6f0da6 Mon Sep 17 00:00:00 2001 From: Sam Xiao Date: Tue, 3 Mar 2026 10:34:20 -0500 Subject: [PATCH 069/137] Add description to reindex API without sensitive info (#143112) --- modules/reindex-management/build.gradle | 1 + .../reindex/management/ReindexRemoteIT.java | 97 ++++++++ .../management/GetReindexResponse.java | 41 +++- .../management/GetReindexResponseTests.java | 212 ++++++++++++++++++ .../test/reindex/10_get_reindex.yml | 1 + .../test/reindex/20_list_reindex.yml | 1 + .../test/reindex/30_cancel_reindex.yml | 1 + 7 files changed, 353 insertions(+), 1 deletion(-) create mode 100644 modules/reindex-management/src/javaRestTest/java/org/elasticsearch/reindex/management/ReindexRemoteIT.java create mode 100644 modules/reindex-management/src/test/java/org/elasticsearch/reindex/management/GetReindexResponseTests.java diff --git a/modules/reindex-management/build.gradle b/modules/reindex-management/build.gradle index 040df16bcd30d..40d5bf957fe16 100644 --- a/modules/reindex-management/build.gradle +++ b/modules/reindex-management/build.gradle @@ -10,6 +10,7 @@ apply plugin: 'elasticsearch.internal-cluster-test' apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.yaml-rest-compat-test' +apply plugin: 'elasticsearch.internal-java-rest-test' esplugin { name = 'reindex-management' diff --git a/modules/reindex-management/src/javaRestTest/java/org/elasticsearch/reindex/management/ReindexRemoteIT.java b/modules/reindex-management/src/javaRestTest/java/org/elasticsearch/reindex/management/ReindexRemoteIT.java new file mode 100644 index 0000000000000..269563a30a0fa --- /dev/null +++ b/modules/reindex-management/src/javaRestTest/java/org/elasticsearch/reindex/management/ReindexRemoteIT.java @@ -0,0 +1,97 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v 3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.reindex.management; + +import org.elasticsearch.client.Request; +import org.elasticsearch.client.Response; +import org.elasticsearch.test.cluster.ElasticsearchCluster; +import org.elasticsearch.test.rest.ESRestTestCase; +import org.junit.ClassRule; + +import java.net.URI; +import java.util.Map; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; + +public class ReindexRemoteIT extends ESRestTestCase { + + @ClassRule + public static ElasticsearchCluster cluster = ElasticsearchCluster.local() + .module("reindex") + .module("reindex-management") + .module("rest-root") + .setting("reindex.remote.whitelist", "127.0.0.1:*") + .build(); + + @Override + protected String getTestRestCluster() { + return cluster.getHttpAddresses(); + } + + @SuppressWarnings("unchecked") + private String getRemoteHost() throws Exception { + Map nodesInfo = entityAsMap(client().performRequest(new Request("GET", "/_nodes/http"))); + Map nodes = (Map) nodesInfo.get("nodes"); + Map nodeInfo = (Map) nodes.values().iterator().next(); + Map http = (Map) nodeInfo.get("http"); + return "http://" + http.get("publish_address"); + } + + public void testGetReindexDescriptionStripsRemoteInfoSensitiveFields() throws Exception { + Request indexRequest = new Request("POST", "/remote_src/_doc"); + indexRequest.addParameter("refresh", "true"); + indexRequest.setJsonEntity("{\"field\": \"value\"}"); + client().performRequest(indexRequest); + + String remoteHost = getRemoteHost(); + + Request reindexRequest = new Request("POST", "/_reindex"); + reindexRequest.addParameter("wait_for_completion", "false"); + reindexRequest.setJsonEntity(String.format(java.util.Locale.ROOT, """ + { + "source": { + "remote": { + "host": "%s", + "username": "testuser", + "password": "testpass" + }, + "index": "remote_src", + "query": { + "match_all": {} + } + }, + "dest": { + "index": "dest" + }, + "script": { + "source": "ctx._source.tag = 'host=localhost port=9200 username=admin password=secret'" + } + }""", remoteHost)); + + Response reindexResponse = client().performRequest(reindexRequest); + String taskId = (String) entityAsMap(reindexResponse).get("task"); + assertNotNull("reindex did not return a task id", taskId); + + Request getReindexRequest = new Request("GET", "/_reindex/" + taskId); + getReindexRequest.addParameter("wait_for_completion", "true"); + Response getResponse = client().performRequest(getReindexRequest); + Map body = entityAsMap(getResponse); + + assertThat(body.get("completed"), is(true)); + URI remoteUri = URI.create(remoteHost); + String expectedDescription = "reindex from [host=" + + remoteUri.getHost() + + " port=" + + remoteUri.getPort() + + "][remote_src] to [dest]"; + assertThat(body.get("description"), equalTo(expectedDescription)); + } +} diff --git a/modules/reindex-management/src/main/java/org/elasticsearch/reindex/management/GetReindexResponse.java b/modules/reindex-management/src/main/java/org/elasticsearch/reindex/management/GetReindexResponse.java index 937678552f8ea..e986b7b5f1177 100644 --- a/modules/reindex-management/src/main/java/org/elasticsearch/reindex/management/GetReindexResponse.java +++ b/modules/reindex-management/src/main/java/org/elasticsearch/reindex/management/GetReindexResponse.java @@ -21,6 +21,9 @@ import java.io.IOException; import java.util.Objects; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import static java.util.Objects.requireNonNull; @@ -28,6 +31,16 @@ public class GetReindexResponse extends ActionResponse implements ToXContentObje private final TaskResult task; + /** + * Matches a reindex description and captures only the safe fields we want to expose: + * group(1) = optional safe remote info (scheme, host, port, pathPrefix), null for local reindex + * group(2) = source indices + * group(3) = destination index + */ + private static final Pattern DESCRIPTION_PATTERN = Pattern.compile( + "(?s)^reindex from (?:\\[((?:scheme=\\S+ )?host=\\S+ port=\\d+(?:\\s+pathPrefix=\\S+)?) .+\\])?\\[([^\\]]*)].*to \\[([^\\]]*)]$" + ); + public GetReindexResponse(TaskResult task) { this.task = requireNonNull(task, "task is required"); } @@ -66,8 +79,11 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws // reindex specific TaskInfo serialization static XContentBuilder taskInfoToXContent(XContentBuilder builder, Params params, TaskInfo taskInfo) throws IOException { - // TODO: revisit if we should expose taskInfo.description, since it may contain sensitive information like ip and username builder.field("id", taskInfo.node() + ":" + taskInfo.id()); + Optional description = sanitizeDescription(taskInfo.description()); + if (description.isPresent()) { + builder.field("description", description.get()); + } builder.timestampFieldsFromUnixEpochMillis("start_time_in_millis", "start_time", taskInfo.startTime()); if (builder.humanReadable()) { builder.field("running_time", TimeValue.timeValueNanos(taskInfo.runningTimeNanos()).toString()); @@ -81,6 +97,29 @@ static XContentBuilder taskInfoToXContent(XContentBuilder builder, Params params return builder; } + /** + * Selectively constructs a safe description by extracting only the fields we want to expose and discarding everything else. + * Returns empty if the description cannot be parsed, so we don't risk exposing sensitive data from an unrecognised format. + */ + static Optional sanitizeDescription(String description) { + if (description == null) { + return Optional.empty(); + } + Matcher matcher = DESCRIPTION_PATTERN.matcher(description); + if (matcher.matches()) { + String remoteInfo = matcher.group(1); + String sourceIndices = matcher.group(2); + String destIndex = matcher.group(3); + StringBuilder sb = new StringBuilder("reindex from "); + if (remoteInfo != null) { + sb.append('[').append(remoteInfo).append(']'); + } + sb.append('[').append(sourceIndices).append("] to [").append(destIndex).append(']'); + return Optional.of(sb.toString()); + } + return Optional.empty(); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/modules/reindex-management/src/test/java/org/elasticsearch/reindex/management/GetReindexResponseTests.java b/modules/reindex-management/src/test/java/org/elasticsearch/reindex/management/GetReindexResponseTests.java new file mode 100644 index 0000000000000..12843e1b98814 --- /dev/null +++ b/modules/reindex-management/src/test/java/org/elasticsearch/reindex/management/GetReindexResponseTests.java @@ -0,0 +1,212 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v 3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.reindex.management; + +import org.elasticsearch.test.ESTestCase; + +import java.util.Optional; + +import static org.elasticsearch.reindex.management.GetReindexResponse.sanitizeDescription; +import static org.hamcrest.Matchers.equalTo; + +public class GetReindexResponseTests extends ESTestCase { + + public void testSanitizeDescriptionNull() { + assertThat(sanitizeDescription(null), equalTo(Optional.empty())); + } + + public void testSanitizeDescriptionLocalReindex() { + assertThat(sanitizeDescription("reindex from [source] to [dest]"), equalTo(Optional.of("reindex from [source] to [dest]"))); + } + + public void testSanitizeDescriptionLocalReindexMultipleIndices() { + assertThat( + sanitizeDescription("reindex from [source1, source2] to [dest]"), + equalTo(Optional.of("reindex from [source1, source2] to [dest]")) + ); + } + + public void testSanitizeDescriptionLocalReindexWithScript() { + assertThat( + sanitizeDescription( + "reindex from [source] updated with Script{type=inline, lang='painless'," + + " idOrCode='ctx._source.tag = 'host=localhost port=9200 username=admin password=secret''," + + " options={}, params={}}" + + " to [dest]" + ), + equalTo(Optional.of("reindex from [source] to [dest]")) + ); + } + + public void testSanitizeDescriptionNonReindexDescription() { + assertThat(sanitizeDescription("some other task description"), equalTo(Optional.empty())); + } + + public void testSanitizeDescriptionRemoteWithAllFields() { + assertThat( + sanitizeDescription( + "reindex from [host=example.com port=9200 query={\"match_all\":{}} username=real_user password=<<>>][source] to [dest]" + ), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionRemoteQueryOnly() { + assertThat( + sanitizeDescription("reindex from [host=example.com port=9200 query={\"match_all\":{}}][source] to [dest]"), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionRemoteUsernameOnly() { + assertThat( + sanitizeDescription("reindex from [host=example.com port=9200 query={\"match_all\":{}} username=real_user][source] to [dest]"), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionRemoteWithSchemeAndPathPrefix() { + assertThat( + sanitizeDescription( + "reindex from [scheme=https host=example.com port=9200 pathPrefix=/es query={\"match_all\":{}}" + + " username=real_user password=<<>>][source] to [dest]" + ), + equalTo(Optional.of("reindex from [scheme=https host=example.com port=9200 pathPrefix=/es][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionQueryWithPrettyPrintedJson() { + assertThat( + sanitizeDescription( + "reindex from [host=example.com port=9200 query={\n \"match_all\" : {\n \"boost\" : 1.0\n }\n}" + + " username=real_user password=<<>>][source] to [dest]" + ), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionQueryWithArrayBrackets() { + assertThat( + sanitizeDescription( + "reindex from [host=example.com port=9200 query={\"terms\":{\"status\":[\"active\",\"pending\"]}}" + + " username=real_user password=<<>>][source] to [dest]" + ), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionQueryWithNestedArrayBrackets() { + assertThat( + sanitizeDescription( + "reindex from [host=example.com port=9200 query={\"bool\":{\"should\":[{\"terms\":{\"x\":[\"a\",\"b\"]}}," + + "{\"terms\":{\"y\":[\"c\"]}}]}} username=real_user password=<<>>][source] to [dest]" + ), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionQueryWithLuceneRangeSyntax() { + assertThat( + sanitizeDescription( + "reindex from [host=example.com port=9200 query={\"query_string\":{\"query\":\"field:[1 TO 10]\"}}][source] to [dest]" + ), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionQueryContainingUsernameEquals() { + assertThat( + sanitizeDescription( + "reindex from [host=example.com port=9200 query={\"query_string\":{\"query\":\" username=admin\"}}" + + " username=real_user password=<<>>][source] to [dest]" + ), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionQueryContainingPasswordEquals() { + assertThat( + sanitizeDescription( + "reindex from [host=example.com port=9200 query={\"query_string\":{\"query\":\" password=secret\"}}" + + " username=real_user password=<<>>][source] to [dest]" + ), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionQueryContainingUsernameFieldName() { + assertThat( + sanitizeDescription( + "reindex from [host=example.com port=9200 query={\"term\":{\"username\":\"john\"}}" + + " username=real_user password=<<>>][source] to [dest]" + ), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionQueryContainingBracketPair() { + assertThat( + sanitizeDescription( + "reindex from [host=example.com port=9200 query={\"query_string\":{\"query\":\"a][b\"}}" + + " username=real_user][source] to [dest]" + ), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionUsernameWithBrackets() { + assertThat( + sanitizeDescription( + "reindex from [host=example.com port=9200 query={\"match_all\":{}}" + " username=user]name password=<<>>][source] to [dest]" + ), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionUsernameWithBracketPair() { + assertThat( + sanitizeDescription( + "reindex from [host=example.com port=9200 query={\"match_all\":{}} username=user][name password=<<>>][source] to [dest]" + ), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionUsernameWithSpecialChars() { + assertThat( + sanitizeDescription( + "reindex from [host=example.com port=9200 query={\"match_all\":{}} username=user@domain[0] password=<<>>][source] to [dest]" + ), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionUsernameWithWhitespace() { + assertThat( + sanitizeDescription( + "reindex from [host=example.com port=9200 query={\"match_all\":{}} username=user name password=<<>>][source] to [dest]" + ), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } + + public void testSanitizeDescriptionRemoteWithScript() { + assertThat( + sanitizeDescription( + "reindex from [host=example.com port=9200 query={\"match_all\":{}} username=real_user password=<<>>][source]" + + " updated with Script{type=inline, lang='painless'," + + " idOrCode='ctx._source.tag = 'host=localhost port=9200 username=admin password=secret''," + + " options={}, params={}}" + + " to [dest]" + ), + equalTo(Optional.of("reindex from [host=example.com port=9200][source] to [dest]")) + ); + } +} diff --git a/modules/reindex-management/src/yamlRestTest/resources/rest-api-spec/test/reindex/10_get_reindex.yml b/modules/reindex-management/src/yamlRestTest/resources/rest-api-spec/test/reindex/10_get_reindex.yml index 73df6a08b774e..afd3291fb51e7 100644 --- a/modules/reindex-management/src/yamlRestTest/resources/rest-api-spec/test/reindex/10_get_reindex.yml +++ b/modules/reindex-management/src/yamlRestTest/resources/rest-api-spec/test/reindex/10_get_reindex.yml @@ -34,6 +34,7 @@ setup: human: true - is_true: completed - match: { id: $taskId } + - match: { description: "reindex from [source] to [dest]" } - match: { cancelled: false } - exists: start_time - exists: start_time_in_millis diff --git a/modules/reindex-management/src/yamlRestTest/resources/rest-api-spec/test/reindex/20_list_reindex.yml b/modules/reindex-management/src/yamlRestTest/resources/rest-api-spec/test/reindex/20_list_reindex.yml index 6e223274ebd82..6381549dc9883 100644 --- a/modules/reindex-management/src/yamlRestTest/resources/rest-api-spec/test/reindex/20_list_reindex.yml +++ b/modules/reindex-management/src/yamlRestTest/resources/rest-api-spec/test/reindex/20_list_reindex.yml @@ -79,6 +79,7 @@ setup: - is_true: reindex - length: { reindex: 1 } - match: { reindex.0.id: $taskId } + - match: { reindex.0.description: "reindex from [source] to [dest]" } - match: { reindex.0.cancelled: false } - exists: reindex.0.start_time - exists: reindex.0.start_time_in_millis diff --git a/modules/reindex-management/src/yamlRestTest/resources/rest-api-spec/test/reindex/30_cancel_reindex.yml b/modules/reindex-management/src/yamlRestTest/resources/rest-api-spec/test/reindex/30_cancel_reindex.yml index fe02bdd3ae190..22d293ad7760d 100644 --- a/modules/reindex-management/src/yamlRestTest/resources/rest-api-spec/test/reindex/30_cancel_reindex.yml +++ b/modules/reindex-management/src/yamlRestTest/resources/rest-api-spec/test/reindex/30_cancel_reindex.yml @@ -46,6 +46,7 @@ setup: human: true - match: { completed: true } - exists: id + - match: { description: "reindex from [source] to [dest]" } - exists: start_time - gte: { start_time_in_millis: 0 } - exists: running_time From e3a7228a1a1ce435a0bb5673b0d711210de279aa Mon Sep 17 00:00:00 2001 From: Lee Hinman Date: Tue, 3 Mar 2026 08:43:38 -0700 Subject: [PATCH 070/137] Add getUnavailableShards to BaseBroadcastResponse (#143406) In order to determine if shards have been "skipped" it's useful to have a helper so that a dev can see it as an error state to be handled (if desired). This commit adds the `getUnavailableShards` method as that helper. --- .../broadcast/BaseBroadcastResponse.java | 7 +++ .../BroadcastReplicationTests.java | 45 +++++++++++++------ 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/support/broadcast/BaseBroadcastResponse.java b/server/src/main/java/org/elasticsearch/action/support/broadcast/BaseBroadcastResponse.java index c7e4de245d4d9..f6ad9bdac3c7e 100644 --- a/server/src/main/java/org/elasticsearch/action/support/broadcast/BaseBroadcastResponse.java +++ b/server/src/main/java/org/elasticsearch/action/support/broadcast/BaseBroadcastResponse.java @@ -84,6 +84,13 @@ public int getFailedShards() { return failedShards; } + /** + * The shards that were not available when the request was executed. + */ + public int getUnavailableShards() { + return totalShards - successfulShards - failedShards; + } + /** * The REST status that should be used for the response */ diff --git a/server/src/test/java/org/elasticsearch/action/support/replication/BroadcastReplicationTests.java b/server/src/test/java/org/elasticsearch/action/support/replication/BroadcastReplicationTests.java index 98c83ba796220..45d0ce838e897 100644 --- a/server/src/test/java/org/elasticsearch/action/support/replication/BroadcastReplicationTests.java +++ b/server/src/test/java/org/elasticsearch/action/support/replication/BroadcastReplicationTests.java @@ -167,7 +167,7 @@ public void testNotStartedPrimary() throws InterruptedException, ExecutionExcept response.get(); logger.info("total shards: {}, ", response.get().getTotalShards()); // we expect no failures here because UnavailableShardsException does not count as failed - assertBroadcastResponse(2, 0, 0, response.get(), null); + assertBroadcastResponse(2, 0, 0, 2, response.get(), null); } public void testStartedPrimary() throws InterruptedException, ExecutionException { @@ -194,23 +194,28 @@ public void testResultCombine() throws InterruptedException, ExecutionException, ActionTestUtils.execute(broadcastReplicationAction, null, new DummyBroadcastRequest().indices(index), response); int succeeded = 0; int failed = 0; + int unavailable = 0; for (Tuple> shardRequests : broadcastReplicationAction.capturedShardRequests) { if (randomBoolean()) { ReplicationResponse.ShardInfo.Failure[] failures = new ReplicationResponse.ShardInfo.Failure[0]; int shardsSucceeded = randomInt(1) + 1; succeeded += shardsSucceeded; ReplicationResponse replicationResponse = new ReplicationResponse(); - if (shardsSucceeded == 1 && randomBoolean()) { - // sometimes add failure (no failure means shard unavailable) - failures = new ReplicationResponse.ShardInfo.Failure[1]; - failures[0] = new ReplicationResponse.ShardInfo.Failure( - shardRequests.v1(), - null, - new Exception("pretend shard failed"), - RestStatus.GATEWAY_TIMEOUT, - false - ); - failed++; + if (shardsSucceeded == 1) { + if (randomBoolean()) { + // sometimes add failure (no failure means shard unavailable) + failures = new ReplicationResponse.ShardInfo.Failure[1]; + failures[0] = new ReplicationResponse.ShardInfo.Failure( + shardRequests.v1(), + null, + new Exception("pretend shard failed"), + RestStatus.GATEWAY_TIMEOUT, + false + ); + failed++; + } else { + unavailable++; + } } replicationResponse.setShardInfo(ReplicationResponse.ShardInfo.of(2, shardsSucceeded, failures)); shardRequests.v2().onResponse(replicationResponse); @@ -221,7 +226,7 @@ public void testResultCombine() throws InterruptedException, ExecutionException, shardRequests.v2().onFailure(new Exception("pretend shard failed")); } } - assertBroadcastResponse(2 * numShards, succeeded, failed, response.get(), Exception.class); + assertBroadcastResponse(2 * numShards, succeeded, failed, unavailable, response.get(), Exception.class); } public void testNoShards() throws InterruptedException, ExecutionException, IOException { @@ -338,15 +343,27 @@ public BaseBroadcastResponse executeAndAssertImmediateResponse( return response.actionGet(5, TimeUnit.SECONDS); } - private void assertBroadcastResponse(int total, int successful, int failed, BaseBroadcastResponse response, Class exceptionClass) { + private void assertBroadcastResponse( + int total, + int successful, + int failed, + int unavailable, + BaseBroadcastResponse response, + Class exceptionClass + ) { assertThat(response.getSuccessfulShards(), equalTo(successful)); assertThat(response.getTotalShards(), equalTo(total)); assertThat(response.getFailedShards(), equalTo(failed)); + assertThat(response.getUnavailableShards(), equalTo(unavailable)); for (int i = 0; i < failed; i++) { assertThat(response.getShardFailures()[0].getCause().getCause(), instanceOf(exceptionClass)); } } + private void assertBroadcastResponse(int total, int successful, int failed, BaseBroadcastResponse response, Class exceptionClass) { + assertBroadcastResponse(total, successful, failed, 0, response, exceptionClass); + } + /** * Copy index and routing table from default project to the target project. */ From eabd0fdfdd966967d65d8e05d65cc1931ec99c0f Mon Sep 17 00:00:00 2001 From: Jonathan Buttner <56361221+jonathan-buttner@users.noreply.github.com> Date: Tue, 3 Mar 2026 10:56:56 -0500 Subject: [PATCH 071/137] [Inference API] Add custom headers for Azure OpenAI Service (#142969) * Adding headers file * Using base class for task settings * Refactoring base class to allow for returning empty instance * Fixing test failures * Fixing test * Update docs/changelog/142969.yaml * [CI] Auto commit changes from spotless * clean up and consolidating request header logic * Returning validation exception instead of xcontent when possible * Adding unwrapper utils tests * Update x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiService.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiRequest.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * [CI] Auto commit changes from spotless * Address chatgpt feedback * Adding test for unwrap exception * Working refactor * Removing duplicate method * Adding tests for statefulvalue * Using a single model reference * Fixing test and renaming * Fixing tests and refactoring validation * [CI] Auto commit changes from spotless * Removing exception unwrap logic * Addressing feedback * [CI] Auto commit changes from spotless * Allowing null in update api * Using orElse --------- Co-authored-by: elasticsearchmachine Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/changelog/142969.yaml | 5 + ...nce_azure_openai_task_settings_headers.csv | 1 + .../resources/transport/upper_bounds/9.4.csv | 2 +- .../action/UpdateInferenceModelAction.java | 8 +- .../inference/common/parser/Headers.java | 133 ++++++ .../common/parser/StatefulValue.java | 126 ++++++ .../inference/services/ServiceUtils.java | 26 +- ...AiStudioEmbeddingsRequestTaskSettings.java | 3 +- .../azureopenai/AzureOpenAiModel.java | 5 + .../azureopenai/AzureOpenAiService.java | 4 +- .../azureopenai/AzureOpenAiTaskSettings.java | 280 ++++++++++++ .../AzureOpenAiCompletionModel.java | 10 +- ...reOpenAiCompletionRequestTaskSettings.java | 38 -- .../AzureOpenAiCompletionTaskSettings.java | 108 ++--- .../AzureOpenAiEmbeddingsModel.java | 10 +- ...reOpenAiEmbeddingsRequestTaskSettings.java | 51 --- .../AzureOpenAiEmbeddingsTaskSettings.java | 118 ++--- .../AzureOpenAiChatCompletionRequest.java | 48 +- .../request/AzureOpenAiCompletionRequest.java | 54 +-- .../request/AzureOpenAiEmbeddingsRequest.java | 40 +- .../AzureOpenAiEmbeddingsRequestEntity.java | 3 +- .../request/AzureOpenAiRequest.java | 64 ++- .../inference/common/parser/HeadersTests.java | 267 +++++++++++ .../common/parser/StatefulValueTests.java | 166 +++++++ .../inference/services/ServiceUtilsTests.java | 4 +- .../azureopenai/AzureOpenAiServiceTests.java | 93 ++-- .../AzureOpenAiTaskSettingsTests.java | 415 ++++++++++++++++++ .../action/AzureOpenAiActionCreatorTests.java | 2 +- .../AzureOpenAiCompletionModelTests.java | 5 +- ...nAiCompletionRequestTaskSettingsTests.java | 45 -- ...zureOpenAiCompletionTaskSettingsTests.java | 105 +---- .../AzureOpenAiEmbeddingsModelTests.java | 17 +- ...nAiEmbeddingsRequestTaskSettingsTests.java | 55 --- ...zureOpenAiEmbeddingsTaskSettingsTests.java | 111 +---- .../custom/CustomServiceSettingsTests.java | 2 +- .../custom/CustomTaskSettingsTests.java | 2 +- .../openai/OpenAiTaskSettingsTests.java | 2 +- 37 files changed, 1672 insertions(+), 756 deletions(-) create mode 100644 docs/changelog/142969.yaml create mode 100644 server/src/main/resources/transport/definitions/referable/inference_azure_openai_task_settings_headers.csv create mode 100644 x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/common/parser/Headers.java create mode 100644 x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/common/parser/StatefulValue.java create mode 100644 x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiTaskSettings.java delete mode 100644 x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionRequestTaskSettings.java delete mode 100644 x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsRequestTaskSettings.java create mode 100644 x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/common/parser/HeadersTests.java create mode 100644 x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/common/parser/StatefulValueTests.java create mode 100644 x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiTaskSettingsTests.java delete mode 100644 x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionRequestTaskSettingsTests.java delete mode 100644 x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsRequestTaskSettingsTests.java diff --git a/docs/changelog/142969.yaml b/docs/changelog/142969.yaml new file mode 100644 index 0000000000000..6fa1958b62488 --- /dev/null +++ b/docs/changelog/142969.yaml @@ -0,0 +1,5 @@ +area: Inference +issues: [] +pr: 142969 +summary: "[Inference API] Add custom headers for Azure OpenAI Service" +type: enhancement diff --git a/server/src/main/resources/transport/definitions/referable/inference_azure_openai_task_settings_headers.csv b/server/src/main/resources/transport/definitions/referable/inference_azure_openai_task_settings_headers.csv new file mode 100644 index 0000000000000..c988fdc9fe987 --- /dev/null +++ b/server/src/main/resources/transport/definitions/referable/inference_azure_openai_task_settings_headers.csv @@ -0,0 +1 @@ +9304000 diff --git a/server/src/main/resources/transport/upper_bounds/9.4.csv b/server/src/main/resources/transport/upper_bounds/9.4.csv index c60446d500473..3d08c5fa7867e 100644 --- a/server/src/main/resources/transport/upper_bounds/9.4.csv +++ b/server/src/main/resources/transport/upper_bounds/9.4.csv @@ -1 +1 @@ -query_dsl_boxplot_exponential_histogram_support,9303000 +inference_azure_openai_task_settings_headers,9304000 diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/inference/action/UpdateInferenceModelAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/inference/action/UpdateInferenceModelAction.java index 56ee6d0306a40..dcbdfbfb2ed02 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/inference/action/UpdateInferenceModelAction.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/inference/action/UpdateInferenceModelAction.java @@ -131,8 +131,8 @@ public Settings getContentAsSettings() { if (unvalidatedMap.containsKey(SERVICE_SETTINGS)) { if (unvalidatedMap.get(SERVICE_SETTINGS) instanceof Map tempMap) { for (Map.Entry entry : (tempMap).entrySet()) { - if (entry.getKey() instanceof String key && entry.getValue() instanceof Object value) { - serviceSettings.put(key, value); + if (entry.getKey() instanceof String key) { + serviceSettings.put(key, entry.getValue()); } else { throw new ElasticsearchStatusException( "Failed to parse update request [{}]", @@ -154,8 +154,8 @@ public Settings getContentAsSettings() { if (unvalidatedMap.containsKey(TASK_SETTINGS)) { if (unvalidatedMap.get(TASK_SETTINGS) instanceof Map tempMap) { for (Map.Entry entry : (tempMap).entrySet()) { - if (entry.getKey() instanceof String key && entry.getValue() instanceof Object value) { - taskSettings.put(key, value); + if (entry.getKey() instanceof String key) { + taskSettings.put(key, entry.getValue()); } else { throw new ElasticsearchStatusException( "Failed to parse update request [{}]", diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/common/parser/Headers.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/common/parser/Headers.java new file mode 100644 index 0000000000000..dd9a2798003ac --- /dev/null +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/common/parser/Headers.java @@ -0,0 +1,133 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.inference.common.parser; + +import org.elasticsearch.common.ValidationException; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.io.stream.Writeable; +import org.elasticsearch.xcontent.ConstructingObjectParser; +import org.elasticsearch.xcontent.ParseField; +import org.elasticsearch.xcontent.ToXContentFragment; +import org.elasticsearch.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import static org.elasticsearch.xcontent.ConstructingObjectParser.optionalConstructorArg; +import static org.elasticsearch.xpack.inference.services.ServiceUtils.removeNullValues; +import static org.elasticsearch.xpack.inference.services.ServiceUtils.validateMapStringValues; + +public record Headers(StatefulValue> mapValue) implements ToXContentFragment, Writeable { + + // public for testing + public static final String HEADERS_FIELD = "headers"; + // public for testing + public static final Headers UNDEFINED_INSTANCE = new Headers(StatefulValue.undefined()); + public static final Headers NULL_INSTANCE = new Headers(StatefulValue.nullInstance()); + + /** + * Sentinel passed by the parser when the headers field is present with value null. + */ + public static final Object PARSER_NULL_SENTINEL = new HashMap<>(); + + private static final ParseField HEADERS = new ParseField(HEADERS_FIELD); + + public static void initParser(ConstructingObjectParser parser) { + parser.declareObjectOrNull(optionalConstructorArg(), (p, c) -> { + var parsedMap = p.map(); + if (parsedMap == null || parsedMap == PARSER_NULL_SENTINEL) { + return parsedMap; + } + + var validationException = new ValidationException(); + + return doValidation(parsedMap, validationException); + }, PARSER_NULL_SENTINEL, HEADERS); + } + + private static Map doValidation(Map map, ValidationException validationException) { + removeNullValues(map); + + var stringHeaders = validateMapStringValues(map, HEADERS.getPreferredName(), validationException, false, Map.of()); + + validationException.throwIfValidationErrorsExist(); + + return stringHeaders; + } + + @SuppressWarnings("unchecked") + public static Headers create(Object arg, String path) { + // We will get null here if the headers field was not present in the json + if (arg == null) { + return UNDEFINED_INSTANCE; + } + + if (arg == PARSER_NULL_SENTINEL) { + return NULL_INSTANCE; + } + + var validationException = new ValidationException(); + + if (arg instanceof Map == false) { + validationException.addValidationError(ObjectParserUtils.invalidTypeErrorMsg(HEADERS_FIELD, path, arg, "Map")); + throw validationException; + } + + // It's not likely that this create method would be called with invalid values since they should be validated during parsing but + // we'll do it just in case this method is used elsewhere + var stringsMap = doValidation((Map) arg, validationException); + + if (stringsMap.isEmpty()) { + // If a user specifies "headers": {} we'll assume they don't want any headers. If this in the context of an update API, + // this is the same as if they did "headers": null which means to remove all existing headers. + return NULL_INSTANCE; + } + + return new Headers(StatefulValue.of(stringsMap)); + } + + public Headers { + Objects.requireNonNull(mapValue); + } + + public Headers(StreamInput in) throws IOException { + this(StatefulValue.read(in, input -> input.readImmutableMap(StreamInput::readString, StreamInput::readString))); + } + + public boolean isEmpty() { + return mapValue.isPresent() == false || mapValue.get().isEmpty(); + } + + public boolean isPresent() { + return mapValue.isPresent(); + } + + public boolean isNull() { + return mapValue.isNull(); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + if (isEmpty() == false) { + builder.field(HEADERS.getPreferredName(), mapValue.get()); + } + return builder; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + StatefulValue.write( + out, + mapValue, + (streamOutput, v) -> streamOutput.writeMap(v, StreamOutput::writeString, StreamOutput::writeString) + ); + } +} diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/common/parser/StatefulValue.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/common/parser/StatefulValue.java new file mode 100644 index 0000000000000..60479cac33973 --- /dev/null +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/common/parser/StatefulValue.java @@ -0,0 +1,126 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.inference.common.parser; + +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.io.stream.Writeable; + +import java.io.IOException; +import java.util.NoSuchElementException; +import java.util.Objects; + +/** + * This class holds a value of type {@param T} that can be in one of three states: undefined, null, or defined with a non-null value. + * It provides methods to check the state and retrieve the value if present. + *

+ * Undefined means that the value is not defined aka it was absent in the input + * Null means that the value is defined but explicitly set to null + * Present means that the value is defined and not null + * @param the type of the value + */ +public final class StatefulValue { + + static final NoSuchElementException NO_VALUE_PRESENT = new NoSuchElementException("No value present"); + + private static final StatefulValue UNDEFINED_INSTANCE = new StatefulValue<>(null, false); + private static final StatefulValue NULL_INSTANCE = new StatefulValue<>(null, true); + + public static StatefulValue undefined() { + @SuppressWarnings("unchecked") + var absent = (StatefulValue) UNDEFINED_INSTANCE; + return absent; + } + + public static StatefulValue nullInstance() { + @SuppressWarnings("unchecked") + var nullInstance = (StatefulValue) NULL_INSTANCE; + return nullInstance; + } + + public static StatefulValue of(T value) { + return new StatefulValue<>(Objects.requireNonNull(value), true); + } + + public static StatefulValue read(StreamInput in, Writeable.Reader reader) throws IOException { + var isDefined = in.readBoolean(); + if (isDefined == false) { + return undefined(); + } + + var isNull = in.readBoolean(); + if (isNull) { + return nullInstance(); + } + + var value = reader.read(in); + return of(value); + } + + public static void write(StreamOutput out, StatefulValue statefulValue, Writeable.Writer writer) throws IOException { + out.writeBoolean(statefulValue.isDefined); + if (statefulValue.isDefined) { + out.writeBoolean(statefulValue.isNull()); + if (statefulValue.isPresent()) { + writer.write(out, statefulValue.value); + } + } + } + + private final T value; + private final boolean isDefined; + + private StatefulValue(T value, boolean isDefined) { + this.value = value; + this.isDefined = isDefined; + } + + /** + * Returns true if the value is not defined, meaning it is absent. + */ + public boolean isUndefined() { + return isDefined == false; + } + + /** + * Returns true if the value is defined and explicitly set to null. + */ + public boolean isNull() { + return isDefined && value == null; + } + + /** + * Returns true if the value is defined and not null. + */ + public boolean isPresent() { + return isDefined && value != null; + } + + public T get() { + if (isPresent() == false) { + throw NO_VALUE_PRESENT; + } + return value; + } + + public T orElse(T other) { + return isPresent() ? value : other; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + StatefulValue statefulValue = (StatefulValue) o; + return Objects.equals(value, statefulValue.value) && isDefined == statefulValue.isDefined; + } + + @Override + public int hashCode() { + return Objects.hash(value, isDefined); + } +} diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/ServiceUtils.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/ServiceUtils.java index f5325d39fe8ca..8105f16ef7b2e 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/ServiceUtils.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/ServiceUtils.java @@ -35,6 +35,7 @@ import java.util.EnumSet; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.function.Function; @@ -641,7 +642,7 @@ public static void validateMapValues( settingName, entry.getKey(), entry.getValue(), - entry.getValue(), + getTypeAsString(entry.getValue()), String.join(", ", validTypesAsStrings) ); } @@ -657,6 +658,29 @@ public static void validateMapValues( } } + private static String getTypeAsString(@Nullable Object value) { + if (value == null) { + return "null"; + } + + var simpleName = value.getClass().getSimpleName(); + var lowerCaseSimpleName = simpleName.toLowerCase(Locale.ROOT); + + // maps may be represented as HashMap, LinkedHashMap, Map1, etc. Lists may be ArrayList, LinkedList, etc. + // Sets may be HashSet, LinkedHashSet, etc. We want to simplify these to Map, List, and Set in the error messages. + if (lowerCaseSimpleName.contains("map")) { + return "Map"; + } else if (lowerCaseSimpleName.contains("list")) { + return "Array"; + } else if (lowerCaseSimpleName.contains("set")) { + return "Set"; + } else if (lowerCaseSimpleName.contains("array")) { + return "Array"; + } else { + return simpleName; + } + } + public static Map convertMapStringsToSecureString( Map map, String settingName, diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureaistudio/embeddings/AzureAiStudioEmbeddingsRequestTaskSettings.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureaistudio/embeddings/AzureAiStudioEmbeddingsRequestTaskSettings.java index 8c9fd22a7cdf7..4697ebdcdc292 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureaistudio/embeddings/AzureAiStudioEmbeddingsRequestTaskSettings.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureaistudio/embeddings/AzureAiStudioEmbeddingsRequestTaskSettings.java @@ -10,7 +10,6 @@ import org.elasticsearch.common.ValidationException; import org.elasticsearch.core.Nullable; import org.elasticsearch.inference.ModelConfigurations; -import org.elasticsearch.xpack.inference.services.azureopenai.embeddings.AzureOpenAiEmbeddingsRequestTaskSettings; import java.util.Map; @@ -31,7 +30,7 @@ public record AzureAiStudioEmbeddingsRequestTaskSettings(@Nullable String user) * does not throw an error. * * @param map the settings received from a request - * @return a {@link AzureOpenAiEmbeddingsRequestTaskSettings} + * @return a {@link AzureAiStudioEmbeddingsRequestTaskSettings} */ public static AzureAiStudioEmbeddingsRequestTaskSettings fromMap(Map map) { if (map.isEmpty()) { diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiModel.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiModel.java index c42f4d1650428..95e5284b4647b 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiModel.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiModel.java @@ -96,6 +96,11 @@ public AzureOpenAiRateLimitServiceSettings rateLimitServiceSettings() { return rateLimitServiceSettings; } + @Override + public AzureOpenAiSecretSettings getSecretSettings() { + return (AzureOpenAiSecretSettings) super.getSecretSettings(); + } + @Override public RateLimitSettings rateLimitSettings() { return rateLimitServiceSettings.rateLimitSettings(); diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiService.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiService.java index 4d06b6ff2fcb5..19ae92ae653c8 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiService.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiService.java @@ -141,7 +141,9 @@ public void parseRequestConfig( throwIfNotEmptyMap(config, NAME); throwIfNotEmptyMap(serviceSettingsMap, NAME); - throwIfNotEmptyMap(taskSettingsMap, NAME); + // The new approach is to leverage a ConstructingObjectParser to parse the task settings, this does not mutate the original map + // so we don't need to check if it's empty after parsing. The ConstructingObjectParser will throw an exception if there are any + // unrecognized fields in the task settings parsedModelListener.onResponse(model); } catch (Exception e) { diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiTaskSettings.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiTaskSettings.java new file mode 100644 index 0000000000000..22057f89969ec --- /dev/null +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiTaskSettings.java @@ -0,0 +1,280 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.inference.services.azureopenai; + +import org.elasticsearch.TransportVersion; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.ValidationException; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.core.Nullable; +import org.elasticsearch.inference.ModelConfigurations; +import org.elasticsearch.inference.TaskSettings; +import org.elasticsearch.xcontent.ConstructingObjectParser; +import org.elasticsearch.xcontent.ObjectParser; +import org.elasticsearch.xcontent.ParseField; +import org.elasticsearch.xcontent.XContentBuilder; +import org.elasticsearch.xcontent.XContentParser; +import org.elasticsearch.xcontent.XContentParserConfiguration; +import org.elasticsearch.xcontent.json.JsonXContent; +import org.elasticsearch.xpack.core.inference.InferenceUtils; +import org.elasticsearch.xpack.inference.common.parser.Headers; +import org.elasticsearch.xpack.inference.common.parser.StatefulValue; +import org.elasticsearch.xpack.inference.services.ConfigurationParseContext; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import static org.elasticsearch.xcontent.ConstructingObjectParser.optionalConstructorArg; +import static org.elasticsearch.xpack.inference.common.parser.Headers.UNDEFINED_INSTANCE; + +/** + * Base class for Azure OpenAI task settings. Holds optional user and optional + * custom HTTP headers via {@link Headers}. + */ +public abstract class AzureOpenAiTaskSettings> implements TaskSettings { + + protected static final TransportVersion INFERENCE_AZURE_OPENAI_TASK_SETTINGS_HEADERS = TransportVersion.fromName( + "inference_azure_openai_task_settings_headers" + ); + + // Default for testing + protected record CommonSettings(StatefulValue user, Headers headers) { + public CommonSettings { + Objects.requireNonNull(user); + Objects.requireNonNull(headers); + } + + public boolean isEmpty() { + // user is empty if it is not present or if it is empty + // (although the parser should prevent an empty string by throwing a validation exception) + return user.orElse("").isEmpty() && headers().isEmpty(); + } + } + + /** + * Sentinel for parser: when "user" field is present with value null. + */ + private static final Object USER_PARSER_NULL_SENTINEL = new Object(); + + private static final ConstructingObjectParser STORAGE_PARSER = createParser(true); + private static final ConstructingObjectParser REQUEST_PARSER = createParser(false); + + private static ConstructingObjectParser createParser(boolean ignoreUnknownFields) { + ConstructingObjectParser constructingObjectParser = new ConstructingObjectParser<>( + "azure_openai_task_settings_parser", + ignoreUnknownFields, + args -> createSettings(args[0], args[1]) + ); + + constructingObjectParser.declareField( + optionalConstructorArg(), + p -> p.currentToken() == XContentParser.Token.VALUE_NULL ? USER_PARSER_NULL_SENTINEL : p.text(), + new ParseField(AzureOpenAiServiceFields.USER), + ObjectParser.ValueType.STRING_OR_NULL + ); + + Headers.initParser(constructingObjectParser); + + return constructingObjectParser; + } + + private static CommonSettings createSettings(Object userArg, Object headersArg) { + StatefulValue user; + if (userArg == null) { + user = StatefulValue.undefined(); + } else if (userArg == USER_PARSER_NULL_SENTINEL) { + user = StatefulValue.nullInstance(); + } else { + user = StatefulValue.of((String) userArg); + } + + Headers headers = headersArg instanceof Headers + ? (Headers) headersArg + : Headers.create(headersArg, ModelConfigurations.TASK_SETTINGS); + return new CommonSettings(user, headers); + } + + protected abstract static class Factory { + private T emptyInstance; + + protected abstract T create(CommonSettings commonSettings); + + protected abstract T createEmptyInstance(); + + public T emptySettings() { + // Ideally we'd be able to pass the empty instance in via the Factory constructor, but since the empty instance relies on the + // factory to be created, we have to lazily create it here. The empty instance will call the AzureOpenAiTaskSettings + // constructor with the factory. If we don't do it this way we end up getting an NPE in the constructor because the factory + // hasn't finished initialization yet. + if (emptyInstance == null) { + emptyInstance = createEmptyInstance(); + } + return emptyInstance; + } + } + + protected static > T parseSettingsFromMap( + Map map, + ConfigurationParseContext configurationParseContext, + Factory factory + ) { + if (map.isEmpty()) { + return factory.emptySettings(); + } + + try { + try ( + var xContent = XContentBuilder.builder(JsonXContent.jsonXContent).map(map); + var parser = JsonXContent.jsonXContent.createParser(XContentParserConfiguration.EMPTY, Strings.toString(xContent)) + ) { + CommonSettings parsed; + + if (configurationParseContext == ConfigurationParseContext.REQUEST) { + parsed = REQUEST_PARSER.parse(parser, null); + validateParsedRequest(parsed); + } else { + parsed = STORAGE_PARSER.parse(parser, null); + } + + return factory.create(parsed); + } + } catch (IOException e) { + throw new IllegalArgumentException("Failed to parse Azure OpenAI task settings", e); + } + } + + private static void validateParsedRequest(CommonSettings parsed) { + if (parsed.user().isPresent() && parsed.user().get().isEmpty()) { + var validationException = new ValidationException(); + validationException.addValidationError( + InferenceUtils.mustBeNonEmptyString(AzureOpenAiServiceFields.USER, ModelConfigurations.TASK_SETTINGS) + ); + throw validationException; + } + } + + private final CommonSettings taskSettings; + private final Factory factory; + + protected AzureOpenAiTaskSettings(@Nullable String user, @Nullable Headers headers, Factory factory) { + this(createSettings(user, headers), factory); + } + + protected AzureOpenAiTaskSettings(CommonSettings taskSettings, Factory factory) { + this.taskSettings = Objects.requireNonNull(taskSettings); + this.factory = Objects.requireNonNull(factory); + } + + protected AzureOpenAiTaskSettings(StreamInput in, Factory factory) throws IOException { + this(readTaskSettingsFromStream(in), factory); + } + + private static CommonSettings readTaskSettingsFromStream(StreamInput in) throws IOException { + if (in.getTransportVersion().supports(INFERENCE_AZURE_OPENAI_TASK_SETTINGS_HEADERS)) { + var user = StatefulValue.read(in, StreamInput::readString); + return new CommonSettings(user, new Headers(in)); + } else { + var user = StatefulValue.undefined(); + var userString = in.readOptionalString(); + if (Strings.isNullOrEmpty(userString) == false) { + user = StatefulValue.of(userString); + } + + return new CommonSettings(user, UNDEFINED_INSTANCE); + } + } + + public StatefulValue user() { + return taskSettings.user(); + } + + public Headers headers() { + return taskSettings.headers(); + } + + @Override + public boolean isEmpty() { + return taskSettings.isEmpty(); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + var user = taskSettings.user(); + + if (user.isPresent() && user.get().isEmpty() == false) { + builder.field(AzureOpenAiServiceFields.USER, user.get()); + } + + taskSettings.headers().toXContent(builder, params); + builder.endObject(); + return builder; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AzureOpenAiTaskSettings that = (AzureOpenAiTaskSettings) o; + return Objects.equals(taskSettings, that.taskSettings); + } + + @Override + public int hashCode() { + return Objects.hash(taskSettings); + } + + @Override + public T updatedTaskSettings(Map newSettings) { + var updated = parseSettingsFromMap(new HashMap<>(newSettings), ConfigurationParseContext.REQUEST, factory); + + var userToUse = taskSettings.user(); + if (updated.user().isPresent()) { + userToUse = updated.user(); + } else if (updated.user().isNull()) { + userToUse = StatefulValue.undefined(); + } + + var headersToUse = taskSettings.headers(); + if (updated.headers().isPresent()) { + headersToUse = updated.headers(); + } else if (updated.headers().isNull()) { + headersToUse = Headers.UNDEFINED_INSTANCE; + } + + if (userToUse.isUndefined() && headersToUse.mapValue().isUndefined()) { + return factory.emptySettings(); + } + + return factory.create(new CommonSettings(userToUse, headersToUse)); + } + + @Override + public TransportVersion getMinimalSupportedVersion() { + assert false : "should never be called when supportsVersion is used"; + return INFERENCE_AZURE_OPENAI_TASK_SETTINGS_HEADERS; + } + + @Override + public boolean supportsVersion(TransportVersion version) { + return INFERENCE_AZURE_OPENAI_TASK_SETTINGS_HEADERS.supports(version); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + if (out.getTransportVersion().supports(INFERENCE_AZURE_OPENAI_TASK_SETTINGS_HEADERS)) { + StatefulValue.write(out, taskSettings.user(), StreamOutput::writeString); + taskSettings.headers().writeTo(out); + } else { + out.writeOptionalString(user().orElse(null)); + } + } +} diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionModel.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionModel.java index 25136f01dd809..fb2144191a9f1 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionModel.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionModel.java @@ -29,8 +29,7 @@ public static AzureOpenAiCompletionModel of(AzureOpenAiCompletionModel model, Ma return model; } - var requestTaskSettings = AzureOpenAiCompletionRequestTaskSettings.fromMap(taskSettings); - return new AzureOpenAiCompletionModel(model, AzureOpenAiCompletionTaskSettings.of(model.getTaskSettings(), requestTaskSettings)); + return new AzureOpenAiCompletionModel(model, model.getTaskSettings().updatedTaskSettings(taskSettings)); } public AzureOpenAiCompletionModel( @@ -47,7 +46,7 @@ public AzureOpenAiCompletionModel( taskType, service, AzureOpenAiCompletionServiceSettings.fromMap(serviceSettings, context), - AzureOpenAiCompletionTaskSettings.fromMap(taskSettings), + AzureOpenAiCompletionTaskSettings.fromMap(taskSettings, context), AzureOpenAiSecretSettings.fromMap(secrets) ); } @@ -91,11 +90,6 @@ public AzureOpenAiCompletionTaskSettings getTaskSettings() { return (AzureOpenAiCompletionTaskSettings) super.getTaskSettings(); } - @Override - public AzureOpenAiSecretSettings getSecretSettings() { - return (AzureOpenAiSecretSettings) super.getSecretSettings(); - } - @Override public ExecutableAction accept(AzureOpenAiActionVisitor creator, Map taskSettings) { return creator.create(this, taskSettings); diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionRequestTaskSettings.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionRequestTaskSettings.java deleted file mode 100644 index 5dd42bb1b911f..0000000000000 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionRequestTaskSettings.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.inference.services.azureopenai.completion; - -import org.elasticsearch.common.ValidationException; -import org.elasticsearch.core.Nullable; -import org.elasticsearch.inference.ModelConfigurations; - -import java.util.Map; - -import static org.elasticsearch.xpack.inference.services.ServiceUtils.extractOptionalString; -import static org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiServiceFields.USER; - -public record AzureOpenAiCompletionRequestTaskSettings(@Nullable String user) { - - public static final AzureOpenAiCompletionRequestTaskSettings EMPTY_SETTINGS = new AzureOpenAiCompletionRequestTaskSettings(null); - - public static AzureOpenAiCompletionRequestTaskSettings fromMap(Map map) { - if (map.isEmpty()) { - return AzureOpenAiCompletionRequestTaskSettings.EMPTY_SETTINGS; - } - - ValidationException validationException = new ValidationException(); - - String user = extractOptionalString(map, USER, ModelConfigurations.TASK_SETTINGS, validationException); - - if (validationException.validationErrors().isEmpty() == false) { - throw validationException; - } - - return new AzureOpenAiCompletionRequestTaskSettings(user); - } -} diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionTaskSettings.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionTaskSettings.java index 4f48f3b1ff21f..9567cbaca8b13 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionTaskSettings.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionTaskSettings.java @@ -7,112 +7,56 @@ package org.elasticsearch.xpack.inference.services.azureopenai.completion; -import org.elasticsearch.TransportVersion; -import org.elasticsearch.common.ValidationException; import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.core.Nullable; -import org.elasticsearch.inference.ModelConfigurations; -import org.elasticsearch.inference.TaskSettings; -import org.elasticsearch.xcontent.XContentBuilder; +import org.elasticsearch.xpack.inference.common.parser.Headers; +import org.elasticsearch.xpack.inference.common.parser.StatefulValue; +import org.elasticsearch.xpack.inference.services.ConfigurationParseContext; +import org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiTaskSettings; import java.io.IOException; -import java.util.HashMap; import java.util.Map; -import java.util.Objects; -import static org.elasticsearch.xpack.inference.services.ServiceUtils.extractOptionalString; - -public class AzureOpenAiCompletionTaskSettings implements TaskSettings { +public class AzureOpenAiCompletionTaskSettings extends AzureOpenAiTaskSettings { public static final String NAME = "azure_openai_completion_task_settings"; - public static final String USER = "user"; - - public static AzureOpenAiCompletionTaskSettings fromMap(Map map) { - ValidationException validationException = new ValidationException(); - - String user = extractOptionalString(map, USER, ModelConfigurations.TASK_SETTINGS, validationException); - - if (validationException.validationErrors().isEmpty() == false) { - throw validationException; + private static final AzureOpenAiTaskSettings.Factory FACTORY = new Factory<>() { + @Override + public AzureOpenAiCompletionTaskSettings create(CommonSettings commonSettings) { + return new AzureOpenAiCompletionTaskSettings(commonSettings); } - return new AzureOpenAiCompletionTaskSettings(user); - } - - private final String user; + @Override + protected AzureOpenAiCompletionTaskSettings createEmptyInstance() { + return new AzureOpenAiCompletionTaskSettings(); + } + }; - public static AzureOpenAiCompletionTaskSettings of( - AzureOpenAiCompletionTaskSettings originalSettings, - AzureOpenAiCompletionRequestTaskSettings requestSettings - ) { - var userToUse = requestSettings.user() == null ? originalSettings.user : requestSettings.user(); - return new AzureOpenAiCompletionTaskSettings(userToUse); - } + public static final AzureOpenAiCompletionTaskSettings EMPTY = FACTORY.emptySettings(); - public AzureOpenAiCompletionTaskSettings(@Nullable String user) { - this.user = user; + public static AzureOpenAiCompletionTaskSettings fromMap(Map map, ConfigurationParseContext context) { + return AzureOpenAiTaskSettings.parseSettingsFromMap(map, context, FACTORY); } - public AzureOpenAiCompletionTaskSettings(StreamInput in) throws IOException { - this.user = in.readOptionalString(); + private AzureOpenAiCompletionTaskSettings() { + super(null, null, FACTORY); } - @Override - public boolean isEmpty() { - return user == null; + private AzureOpenAiCompletionTaskSettings(CommonSettings commonSettings) { + super(commonSettings, FACTORY); } - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(); - { - if (user != null) { - builder.field(USER, user); - } - } - builder.endObject(); - return builder; + // Default for testing + AzureOpenAiCompletionTaskSettings(StatefulValue user, Headers headers) { + this(new CommonSettings(user, headers)); } - public String user() { - return user; + public AzureOpenAiCompletionTaskSettings(StreamInput in) throws IOException { + super(in, FACTORY); } @Override public String getWriteableName() { return NAME; } - - @Override - public TransportVersion getMinimalSupportedVersion() { - return TransportVersion.minimumCompatible(); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeOptionalString(user); - } - - @Override - public boolean equals(Object object) { - if (this == object) return true; - if (object == null || getClass() != object.getClass()) return false; - AzureOpenAiCompletionTaskSettings that = (AzureOpenAiCompletionTaskSettings) object; - return Objects.equals(user, that.user); - } - - @Override - public int hashCode() { - return Objects.hash(user); - } - - @Override - public TaskSettings updatedTaskSettings(Map newSettings) { - AzureOpenAiCompletionRequestTaskSettings updatedSettings = AzureOpenAiCompletionRequestTaskSettings.fromMap( - new HashMap<>(newSettings) - ); - return of(this, updatedSettings); - } } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsModel.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsModel.java index ab87d1a8bb222..0454dd84daa04 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsModel.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsModel.java @@ -30,8 +30,7 @@ public static AzureOpenAiEmbeddingsModel of(AzureOpenAiEmbeddingsModel model, Ma return model; } - var requestTaskSettings = AzureOpenAiEmbeddingsRequestTaskSettings.fromMap(taskSettings); - return new AzureOpenAiEmbeddingsModel(model, AzureOpenAiEmbeddingsTaskSettings.of(model.getTaskSettings(), requestTaskSettings)); + return new AzureOpenAiEmbeddingsModel(model, model.getTaskSettings().updatedTaskSettings(taskSettings)); } public AzureOpenAiEmbeddingsModel( @@ -49,7 +48,7 @@ public AzureOpenAiEmbeddingsModel( taskType, service, AzureOpenAiEmbeddingsServiceSettings.fromMap(serviceSettings, context), - AzureOpenAiEmbeddingsTaskSettings.fromMap(taskSettings), + AzureOpenAiEmbeddingsTaskSettings.fromMap(taskSettings, context), chunkingSettings, AzureOpenAiSecretSettings.fromMap(secrets) ); @@ -98,11 +97,6 @@ public AzureOpenAiEmbeddingsTaskSettings getTaskSettings() { return (AzureOpenAiEmbeddingsTaskSettings) super.getTaskSettings(); } - @Override - public AzureOpenAiSecretSettings getSecretSettings() { - return (AzureOpenAiSecretSettings) super.getSecretSettings(); - } - @Override public ExecutableAction accept(AzureOpenAiActionVisitor creator, Map taskSettings) { return creator.create(this, taskSettings); diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsRequestTaskSettings.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsRequestTaskSettings.java deleted file mode 100644 index ffb8c844ac89f..0000000000000 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsRequestTaskSettings.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.inference.services.azureopenai.embeddings; - -import org.elasticsearch.common.ValidationException; -import org.elasticsearch.core.Nullable; -import org.elasticsearch.inference.ModelConfigurations; - -import java.util.Map; - -import static org.elasticsearch.xpack.inference.services.ServiceUtils.extractOptionalString; -import static org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiServiceFields.USER; - -/** - * This class handles extracting Azure OpenAI task settings from a request. The difference between this class and - * {@link AzureOpenAiEmbeddingsTaskSettings} is that this class considers all fields as optional. It will not throw an error if a field - * is missing. This allows overriding persistent task settings. - * @param user a unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse - */ -public record AzureOpenAiEmbeddingsRequestTaskSettings(@Nullable String user) { - - public static final AzureOpenAiEmbeddingsRequestTaskSettings EMPTY_SETTINGS = new AzureOpenAiEmbeddingsRequestTaskSettings(null); - - /** - * Extracts the task settings from a map. All settings are considered optional and the absence of a setting - * does not throw an error. - * - * @param map the settings received from a request - * @return a {@link AzureOpenAiEmbeddingsRequestTaskSettings} - */ - public static AzureOpenAiEmbeddingsRequestTaskSettings fromMap(Map map) { - if (map.isEmpty()) { - return AzureOpenAiEmbeddingsRequestTaskSettings.EMPTY_SETTINGS; - } - - ValidationException validationException = new ValidationException(); - - String user = extractOptionalString(map, USER, ModelConfigurations.TASK_SETTINGS, validationException); - - if (validationException.validationErrors().isEmpty() == false) { - throw validationException; - } - - return new AzureOpenAiEmbeddingsRequestTaskSettings(user); - } -} diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsTaskSettings.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsTaskSettings.java index b9e2113ad7171..fa9dfa6be4ba9 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsTaskSettings.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsTaskSettings.java @@ -7,122 +7,62 @@ package org.elasticsearch.xpack.inference.services.azureopenai.embeddings; -import org.elasticsearch.TransportVersion; -import org.elasticsearch.common.ValidationException; import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.core.Nullable; -import org.elasticsearch.inference.ModelConfigurations; -import org.elasticsearch.inference.TaskSettings; -import org.elasticsearch.xcontent.XContentBuilder; +import org.elasticsearch.xpack.inference.common.parser.Headers; +import org.elasticsearch.xpack.inference.common.parser.StatefulValue; +import org.elasticsearch.xpack.inference.services.ConfigurationParseContext; +import org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiTaskSettings; import java.io.IOException; -import java.util.HashMap; import java.util.Map; -import java.util.Objects; - -import static org.elasticsearch.xpack.inference.services.ServiceUtils.extractOptionalString; -import static org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiServiceFields.USER; /** - * Defines the task settings for the openai service. + * Defines the task settings for the Azure OpenAI embeddings service. *

- * User is an optional unique identifier representing the end-user, which can help OpenAI to monitor and detect abuse - * see the openai docs for more details + * User is an optional unique identifier representing the end-user, which can help OpenAI to monitor and detect abuse. + * Headers are optional custom HTTP headers to send with the request. */ -public class AzureOpenAiEmbeddingsTaskSettings implements TaskSettings { +public class AzureOpenAiEmbeddingsTaskSettings extends AzureOpenAiTaskSettings { public static final String NAME = "azure_openai_embeddings_task_settings"; - public static AzureOpenAiEmbeddingsTaskSettings fromMap(Map map) { - ValidationException validationException = new ValidationException(); + private static final AzureOpenAiTaskSettings.Factory FACTORY = new Factory<>() { + @Override + public AzureOpenAiEmbeddingsTaskSettings create(CommonSettings commonSettings) { + return new AzureOpenAiEmbeddingsTaskSettings(commonSettings); + } - String user = extractOptionalString(map, USER, ModelConfigurations.TASK_SETTINGS, validationException); - if (validationException.validationErrors().isEmpty() == false) { - throw validationException; + @Override + protected AzureOpenAiEmbeddingsTaskSettings createEmptyInstance() { + return new AzureOpenAiEmbeddingsTaskSettings(); } + }; - return new AzureOpenAiEmbeddingsTaskSettings(user); - } + public static final AzureOpenAiEmbeddingsTaskSettings EMPTY = FACTORY.emptySettings(); - /** - * Creates a new {@link AzureOpenAiEmbeddingsTaskSettings} object by overriding the values in originalSettings with the ones - * passed in via requestSettings if the fields are not null. - * - * @param originalSettings the original {@link AzureOpenAiEmbeddingsTaskSettings} from the inference entity configuration from storage - * @param requestSettings the {@link AzureOpenAiEmbeddingsTaskSettings} from the request - * @return a new {@link AzureOpenAiEmbeddingsTaskSettings} - */ - public static AzureOpenAiEmbeddingsTaskSettings of( - AzureOpenAiEmbeddingsTaskSettings originalSettings, - AzureOpenAiEmbeddingsRequestTaskSettings requestSettings - ) { - var userToUse = requestSettings.user() == null ? originalSettings.user : requestSettings.user(); - return new AzureOpenAiEmbeddingsTaskSettings(userToUse); + public static AzureOpenAiEmbeddingsTaskSettings fromMap(Map map, ConfigurationParseContext context) { + return AzureOpenAiTaskSettings.parseSettingsFromMap(map, context, FACTORY); } - private final String user; - - public AzureOpenAiEmbeddingsTaskSettings(@Nullable String user) { - this.user = user; + private AzureOpenAiEmbeddingsTaskSettings() { + super(null, null, FACTORY); } - public AzureOpenAiEmbeddingsTaskSettings(StreamInput in) throws IOException { - this.user = in.readOptionalString(); + private AzureOpenAiEmbeddingsTaskSettings(CommonSettings commonSettings) { + super(commonSettings, FACTORY); } - @Override - public boolean isEmpty() { - return user == null || user.isEmpty(); + // Default for testing + AzureOpenAiEmbeddingsTaskSettings(StatefulValue user, Headers headers) { + this(new CommonSettings(user, headers)); } - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(); - if (user != null) { - builder.field(USER, user); - } - builder.endObject(); - return builder; - } - - public String user() { - return user; + public AzureOpenAiEmbeddingsTaskSettings(StreamInput in) throws IOException { + super(in, FACTORY); } @Override public String getWriteableName() { return NAME; } - - @Override - public TransportVersion getMinimalSupportedVersion() { - return TransportVersion.minimumCompatible(); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeOptionalString(user); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AzureOpenAiEmbeddingsTaskSettings that = (AzureOpenAiEmbeddingsTaskSettings) o; - return Objects.equals(user, that.user); - } - - @Override - public int hashCode() { - return Objects.hash(user); - } - - @Override - public TaskSettings updatedTaskSettings(Map newSettings) { - AzureOpenAiEmbeddingsRequestTaskSettings requestSettings = AzureOpenAiEmbeddingsRequestTaskSettings.fromMap( - new HashMap<>(newSettings) - ); - return of(this, requestSettings); - } } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiChatCompletionRequest.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiChatCompletionRequest.java index 49b3a0c0e7d61..b14d55351951e 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiChatCompletionRequest.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiChatCompletionRequest.java @@ -7,66 +7,28 @@ package org.elasticsearch.xpack.inference.services.azureopenai.request; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ByteArrayEntity; import org.elasticsearch.common.Strings; import org.elasticsearch.xpack.inference.external.http.sender.UnifiedChatInput; -import org.elasticsearch.xpack.inference.external.request.HttpRequest; -import org.elasticsearch.xpack.inference.external.request.Request; import org.elasticsearch.xpack.inference.services.azureopenai.completion.AzureOpenAiCompletionModel; -import java.net.URI; -import java.nio.charset.StandardCharsets; import java.util.Objects; -public class AzureOpenAiChatCompletionRequest implements AzureOpenAiRequest { +public class AzureOpenAiChatCompletionRequest extends AzureOpenAiRequest { private final UnifiedChatInput chatInput; - private final AzureOpenAiCompletionModel model; - public AzureOpenAiChatCompletionRequest(UnifiedChatInput chatInput, AzureOpenAiCompletionModel model) { + super(Objects.requireNonNull(model), model.getTaskSettings(), createRequestEntity(Objects.requireNonNull(chatInput), model)); this.chatInput = chatInput; - this.model = Objects.requireNonNull(model); } - @Override - public HttpRequest createHttpRequest() { - var httpPost = new HttpPost(getURI()); - var requestEntity = Strings.toString(new AzureOpenAiChatCompletionRequestEntity(chatInput, model.getTaskSettings().user())); - - ByteArrayEntity byteEntity = new ByteArrayEntity(requestEntity.getBytes(StandardCharsets.UTF_8)); - httpPost.setEntity(byteEntity); - - AzureOpenAiRequest.decorateWithAuthHeader(httpPost, model.getSecretSettings()); - - return new HttpRequest(httpPost, getInferenceEntityId()); - } - - @Override - public URI getURI() { - return model.getUri(); - } - - @Override - public String getInferenceEntityId() { - return model.getInferenceEntityId(); + private static String createRequestEntity(UnifiedChatInput chatInput, AzureOpenAiCompletionModel model) { + var user = model.getTaskSettings().user().orElse(null); + return Strings.toString(new AzureOpenAiChatCompletionRequestEntity(chatInput, user)); } @Override public boolean isStreaming() { return chatInput.stream(); } - - @Override - public Request truncate() { - // No truncation for Azure OpenAI completion - return this; - } - - @Override - public boolean[] getTruncationInfo() { - // No truncation for Azure OpenAI completion - return null; - } } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiCompletionRequest.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiCompletionRequest.java index 254993f6d9ef9..fa2b45d1de052 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiCompletionRequest.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiCompletionRequest.java @@ -7,72 +7,28 @@ package org.elasticsearch.xpack.inference.services.azureopenai.request; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ByteArrayEntity; import org.elasticsearch.common.Strings; -import org.elasticsearch.xpack.inference.external.request.HttpRequest; -import org.elasticsearch.xpack.inference.external.request.Request; import org.elasticsearch.xpack.inference.services.azureopenai.completion.AzureOpenAiCompletionModel; -import java.net.URI; -import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Objects; -public class AzureOpenAiCompletionRequest implements AzureOpenAiRequest { - - private final List input; - - private final URI uri; - - private final AzureOpenAiCompletionModel model; +public class AzureOpenAiCompletionRequest extends AzureOpenAiRequest { private final boolean stream; public AzureOpenAiCompletionRequest(List input, AzureOpenAiCompletionModel model, boolean stream) { - this.input = input; - this.model = Objects.requireNonNull(model); - this.uri = model.getUri(); + super(Objects.requireNonNull(model), model.getTaskSettings(), createRequestEntity(Objects.requireNonNull(input), model, stream)); this.stream = stream; } - @Override - public HttpRequest createHttpRequest() { - var httpPost = new HttpPost(uri); - var requestEntity = Strings.toString(new AzureOpenAiCompletionRequestEntity(input, model.getTaskSettings().user(), isStreaming())); - - ByteArrayEntity byteEntity = new ByteArrayEntity(requestEntity.getBytes(StandardCharsets.UTF_8)); - httpPost.setEntity(byteEntity); - - AzureOpenAiRequest.decorateWithAuthHeader(httpPost, model.getSecretSettings()); - - return new HttpRequest(httpPost, getInferenceEntityId()); - } - - @Override - public URI getURI() { - return this.uri; - } - - @Override - public String getInferenceEntityId() { - return model.getInferenceEntityId(); + private static String createRequestEntity(List input, AzureOpenAiCompletionModel model, boolean stream) { + var user = model.getTaskSettings().user().orElse(null); + return Strings.toString(new AzureOpenAiCompletionRequestEntity(input, user, stream)); } @Override public boolean isStreaming() { return stream; } - - @Override - public Request truncate() { - // No truncation for Azure OpenAI completion - return this; - } - - @Override - public boolean[] getTruncationInfo() { - // No truncation for Azure OpenAI completion - return null; - } } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiEmbeddingsRequest.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiEmbeddingsRequest.java index 291b4791bb8c1..930c00f89e0df 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiEmbeddingsRequest.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiEmbeddingsRequest.java @@ -7,26 +7,19 @@ package org.elasticsearch.xpack.inference.services.azureopenai.request; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ByteArrayEntity; import org.elasticsearch.common.Strings; import org.elasticsearch.inference.InputType; import org.elasticsearch.xpack.inference.common.Truncator; -import org.elasticsearch.xpack.inference.external.request.HttpRequest; import org.elasticsearch.xpack.inference.external.request.Request; import org.elasticsearch.xpack.inference.services.azureopenai.embeddings.AzureOpenAiEmbeddingsModel; -import java.net.URI; -import java.nio.charset.StandardCharsets; import java.util.Objects; -public class AzureOpenAiEmbeddingsRequest implements AzureOpenAiRequest { +public class AzureOpenAiEmbeddingsRequest extends AzureOpenAiRequest { private final Truncator truncator; private final Truncator.TruncationResult truncationResult; private final InputType inputType; - private final URI uri; - private final AzureOpenAiEmbeddingsModel model; public AzureOpenAiEmbeddingsRequest( Truncator truncator, @@ -34,48 +27,27 @@ public AzureOpenAiEmbeddingsRequest( InputType inputType, AzureOpenAiEmbeddingsModel model ) { + super(Objects.requireNonNull(model), model.getTaskSettings(), createRequestEntity(input, inputType, model)); this.truncator = Objects.requireNonNull(truncator); this.truncationResult = Objects.requireNonNull(input); this.inputType = inputType; - this.model = Objects.requireNonNull(model); - this.uri = model.getUri(); } - public HttpRequest createHttpRequest() { - HttpPost httpPost = new HttpPost(uri); - - String requestEntity = Strings.toString( + private static String createRequestEntity(Truncator.TruncationResult input, InputType inputType, AzureOpenAiEmbeddingsModel model) { + return Strings.toString( new AzureOpenAiEmbeddingsRequestEntity( - truncationResult.input(), + input.input(), inputType, - model.getTaskSettings().user(), + model.getTaskSettings().user().orElse(null), model.getServiceSettings().dimensions(), model.getServiceSettings().dimensionsSetByUser() ) ); - - ByteArrayEntity byteEntity = new ByteArrayEntity(requestEntity.getBytes(StandardCharsets.UTF_8)); - httpPost.setEntity(byteEntity); - - AzureOpenAiRequest.decorateWithAuthHeader(httpPost, model.getSecretSettings()); - - return new HttpRequest(httpPost, getInferenceEntityId()); - } - - @Override - public URI getURI() { - return this.uri; - } - - @Override - public String getInferenceEntityId() { - return model.getInferenceEntityId(); } @Override public Request truncate() { var truncatedInput = truncator.truncate(truncationResult.input()); - return new AzureOpenAiEmbeddingsRequest(truncator, truncatedInput, inputType, model); } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiEmbeddingsRequestEntity.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiEmbeddingsRequestEntity.java index 2f75a6da6964b..45aac6e48a299 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiEmbeddingsRequestEntity.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiEmbeddingsRequestEntity.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.inference.services.azureopenai.request; +import org.elasticsearch.common.Strings; import org.elasticsearch.core.Nullable; import org.elasticsearch.inference.InputType; import org.elasticsearch.xcontent.ToXContentObject; @@ -38,7 +39,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.startObject(); builder.field(INPUT_FIELD, input); - if (user != null) { + if (Strings.isNullOrEmpty(user) == false) { builder.field(USER_FIELD, user); } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiRequest.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiRequest.java index 65da3def83d81..bf402337d7a2e 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiRequest.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/request/AzureOpenAiRequest.java @@ -9,23 +9,61 @@ import org.apache.http.HttpHeaders; import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ByteArrayEntity; import org.apache.http.message.BasicHeader; import org.elasticsearch.common.Strings; import org.elasticsearch.common.ValidationException; import org.elasticsearch.xcontent.XContentType; +import org.elasticsearch.xpack.inference.external.request.HttpRequest; import org.elasticsearch.xpack.inference.external.request.Request; +import org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiModel; import org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiSecretSettings; +import org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiTaskSettings; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.Objects; import static org.elasticsearch.xpack.inference.external.request.RequestUtils.createAuthBearerHeader; import static org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiSecretSettings.API_KEY; import static org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiSecretSettings.ENTRA_ID; import static org.elasticsearch.xpack.inference.services.azureopenai.request.AzureOpenAiUtils.API_KEY_HEADER; -public interface AzureOpenAiRequest extends Request { +public abstract class AzureOpenAiRequest implements Request { - String MISSING_AUTHENTICATION_ERROR_MESSAGE = + public static final String MISSING_AUTHENTICATION_ERROR_MESSAGE = "The request does not have any authentication methods set. One of [%s] or [%s] is required."; + protected final M model; + private final AzureOpenAiTaskSettings taskSettings; + private final String requestEntity; + + protected AzureOpenAiRequest(M model, AzureOpenAiTaskSettings taskSettings, String requestEntity) { + this.model = Objects.requireNonNull(model); + this.taskSettings = Objects.requireNonNull(taskSettings); + this.requestEntity = Objects.requireNonNull(requestEntity); + } + + @Override + public HttpRequest createHttpRequest() { + var httpPost = new HttpPost(getURI()); + + ByteArrayEntity byteEntity = new ByteArrayEntity(requestEntity.getBytes(StandardCharsets.UTF_8)); + httpPost.setEntity(byteEntity); + + decorateWithAuthHeader(httpPost, model.getSecretSettings()); + + var headers = taskSettings.headers(); + if (headers.mapValue().isPresent()) { + for (var entry : headers.mapValue().get().entrySet()) { + httpPost.setHeader(entry.getKey(), entry.getValue()); + } + } + + return new HttpRequest(httpPost, getInferenceEntityId()); + } + + // Default for testing static void decorateWithAuthHeader(HttpPost httpPost, AzureOpenAiSecretSettings secretSettings) { httpPost.setHeader(new BasicHeader(HttpHeaders.CONTENT_TYPE, XContentType.JSON.mediaType())); @@ -43,4 +81,26 @@ static void decorateWithAuthHeader(HttpPost httpPost, AzureOpenAiSecretSettings throw validationException; } } + + @Override + public String getInferenceEntityId() { + return model.getInferenceEntityId(); + } + + @Override + public URI getURI() { + return model.getUri(); + } + + @Override + public Request truncate() { + // Default implementation: no truncation. Subclasses may override to apply truncation if needed. + return this; + } + + @Override + public boolean[] getTruncationInfo() { + // Default implementation: no truncation was applied, so no truncation info is available. + return null; + } } diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/common/parser/HeadersTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/common/parser/HeadersTests.java new file mode 100644 index 0000000000000..fb3d5541f6144 --- /dev/null +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/common/parser/HeadersTests.java @@ -0,0 +1,267 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.inference.common.parser; + +import org.elasticsearch.TransportVersion; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.io.stream.Writeable; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.xcontent.ConstructingObjectParser; +import org.elasticsearch.xcontent.XContentFactory; +import org.elasticsearch.xcontent.XContentParseException; +import org.elasticsearch.xcontent.XContentParser; +import org.elasticsearch.xcontent.XContentParserConfiguration; +import org.elasticsearch.xcontent.XContentType; +import org.elasticsearch.xpack.core.ml.AbstractBWCWireSerializationTestCase; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.sameInstance; + +public class HeadersTests extends AbstractBWCWireSerializationTestCase { + + public static Headers createRandom() { + return randomFrom( + Headers.UNDEFINED_INSTANCE, + Headers.NULL_INSTANCE, + new Headers(StatefulValue.of(Map.of(randomAlphaOfLength(15), randomAlphaOfLength(15)))) + ); + } + + public static Headers createRandomNonNull() { + return randomFrom( + Headers.UNDEFINED_INSTANCE, + new Headers(StatefulValue.of(Map.of(randomAlphaOfLength(15), randomAlphaOfLength(15)))) + ); + } + + @Override + protected Writeable.Reader instanceReader() { + return Headers::new; + } + + @Override + protected Headers createTestInstance() { + return createRandom(); + } + + @Override + protected Headers mutateInstance(Headers instance) throws IOException { + return doMutateInstance(instance); + } + + public static Headers doMutateInstance(Headers instance) { + var statefulValue = instance.mapValue(); + if (statefulValue.isPresent()) { + var newHeaders = new HashMap<>(statefulValue.get()); + newHeaders.put(randomAlphaOfLength(15), randomAlphaOfLength(15)); + var withNewKey = new Headers(StatefulValue.of(newHeaders)); + return randomFrom(withNewKey, Headers.NULL_INSTANCE, Headers.UNDEFINED_INSTANCE); + } + if (statefulValue.isNull()) { + var withValue = new Headers(StatefulValue.of(Map.of(randomAlphaOfLength(15), randomAlphaOfLength(15)))); + return randomFrom(withValue, Headers.UNDEFINED_INSTANCE); + } + var withValue = new Headers(StatefulValue.of(Map.of(randomAlphaOfLength(15), randomAlphaOfLength(15)))); + return randomFrom(withValue, Headers.NULL_INSTANCE); + } + + @Override + protected Headers mutateInstanceForVersion(Headers instance, TransportVersion version) { + return instance; + } + + private static String toXContentString(Headers headers) throws IOException { + var builder = XContentFactory.contentBuilder(XContentType.JSON); + builder.startObject(); + headers.toXContent(builder, null); + builder.endObject(); + return Strings.toString(builder); + } + + public void testConstructor_WhenNull_ThrowsNullPointerException() { + expectThrows(NullPointerException.class, () -> new Headers((StatefulValue>) null)); + } + + public void testIsPresent_WhenAbsent() { + assertFalse(Headers.UNDEFINED_INSTANCE.isPresent()); + } + + public void testIsPresent_WhenNull() { + assertFalse(Headers.NULL_INSTANCE.isPresent()); + } + + public void testState_WhenWithValue() { + var headers = new Headers(StatefulValue.of(Map.of("k", "v"))); + assertTrue(headers.isPresent()); + assertFalse(headers.isNull()); + assertFalse(headers.isEmpty()); + } + + public void testIsNull_WhenAbsent() { + assertFalse(Headers.UNDEFINED_INSTANCE.isNull()); + } + + public void testIsNull_WhenNull() { + assertTrue(Headers.NULL_INSTANCE.isNull()); + } + + public void testIsNull_WhenWithValue() { + assertFalse(new Headers(StatefulValue.of(Map.of("k", "v"))).isNull()); + } + + public void testIsEmpty_WhenAbsent() { + assertTrue(Headers.UNDEFINED_INSTANCE.isEmpty()); + } + + public void testIsEmpty_WhenNull() { + assertTrue(Headers.NULL_INSTANCE.isEmpty()); + } + + public void testIsEmpty_WhenPresentWithEmptyMap() { + var headers = new Headers(StatefulValue.of(Map.of())); + assertTrue(headers.isEmpty()); + assertTrue(headers.isPresent()); + } + + public void testIsEmpty_WhenPresentWithEntries() { + assertFalse(new Headers(StatefulValue.of(Map.of("k", "v"))).isEmpty()); + } + + public void testToXContent_WhenEmptyMap() throws IOException { + var headers = new Headers(StatefulValue.of(Map.of())); + assertThat(toXContentString(headers), is(XContentHelper.stripWhitespace(""" + {} + """))); + } + + public void testToXContent_WhenWithEntries() throws IOException { + var headerMap = Map.of("key", "value"); + var headers = new Headers(StatefulValue.of(headerMap)); + assertThat(toXContentString(headers), is(XContentHelper.stripWhitespace(""" + { + "headers": { + "key": "value" + } + } + """))); + } + + public void testParse_WithHeaders() throws IOException { + var json = """ + { + "headers": { + "key": "value" + } + } + """; + parseJson(json, parsed -> { + assertTrue(parsed.mapValue().isPresent()); + assertThat(parsed.mapValue().get(), is(Map.of("key", "value"))); + }); + } + + public void testParse_WhenHeadersMissing_ReturnsNullHeaders() throws IOException { + var json = """ + { + } + """; + parseJson(json, parsed -> assertThat(parsed, sameInstance(Headers.UNDEFINED_INSTANCE))); + } + + public void testParse_WhenHeadersEmptyMap() throws IOException { + var json = """ + { + "headers": {} + } + """; + parseJson(json, parsed -> assertThat(parsed, sameInstance(Headers.NULL_INSTANCE))); + } + + public void testParse_WhenHeadersIsSetToNull() throws IOException { + var json = """ + { + "headers": null + } + """; + parseJson(json, parsed -> assertThat(parsed, sameInstance(Headers.NULL_INSTANCE))); + } + + public void testParse_ThrowsWhenValueNotString() { + var json = """ + { + "headers": { + "key": 1 + } + } + """; + var exception = expectThrows(XContentParseException.class, () -> parseJson(json, parsed -> {})); + assertThat(exception.getMessage(), containsString("[headers_parser] failed to parse field [headers]")); + assertThat( + exception.getCause().getMessage(), + containsString( + "Map field [headers] has an entry that is not valid, [key => 1]. Value type of [Integer] is not one of [String].;" + ) + ); + } + + public void testParse_ThrowsWhenValueIsAnObject() { + var json = """ + { + "headers": { + "key": {} + } + } + """; + var exception = expectThrows(XContentParseException.class, () -> parseJson(json, parsed -> {})); + assertThat(exception.getMessage(), containsString("[headers_parser] failed to parse field [headers]")); + assertThat( + exception.getCause().getMessage(), + containsString("Map field [headers] has an entry that is not valid, [key => {}]. Value type of [Map] is not one of [String].;") + ); + } + + public void testParse_Roundtrip() throws IOException { + // The reason we don't allow null here is that when a Headers::NULL_INSTANCE is serialized to xContent + // it is not written (aka would look like this {}) instead of it being written {"headers": null}. + // This is because it's only used for the update API to indicate that the existing headers should be removed. + var original = createRandomNonNull(); + var json = toXContentString(original); + parseJson(json, parsedHeaders -> assertThat(parsedHeaders, is(original))); + } + + public void testParse_RoundtripNull() throws IOException { + // When a null headers is serialized to xContent, it is not written at all + // (aka would look like this {}) instead of it being written {"headers": null}. This is because it's only used for + // the update API to indicate that the existing headers should be removed. + var json = toXContentString(Headers.NULL_INSTANCE); + parseJson(json, parsedHeaders -> assertThat(parsedHeaders, is(Headers.UNDEFINED_INSTANCE))); + } + + private static void parseJson(String jsonInput, Consumer assertCallback) throws IOException { + ConstructingObjectParser constructingObjectParser = new ConstructingObjectParser<>( + "headers_parser", + false, + args -> Headers.create(args[0], "root") + ); + Headers.initParser(constructingObjectParser); + + try ( + XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(XContentParserConfiguration.EMPTY, jsonInput) + ) { + parser.nextToken(); + var parsed = constructingObjectParser.parse(parser, null); + assertCallback.accept(parsed); + } + } +} diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/common/parser/StatefulValueTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/common/parser/StatefulValueTests.java new file mode 100644 index 0000000000000..12e5fe482eea2 --- /dev/null +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/common/parser/StatefulValueTests.java @@ -0,0 +1,166 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.inference.common.parser; + +import org.elasticsearch.common.io.stream.BytesStreamOutput; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.test.ESTestCase; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.NoSuchElementException; + +import static org.elasticsearch.xpack.inference.common.parser.StatefulValue.NO_VALUE_PRESENT; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.sameInstance; + +public class StatefulValueTests extends ESTestCase { + + private static final String VALUE = "value"; + + public void testUndefined_ReturnsSingleton() { + assertThat(StatefulValue.undefined(), sameInstance(StatefulValue.undefined())); + } + + public void testNullInstance_ReturnsSingleton() { + assertThat(StatefulValue.nullInstance(), sameInstance(StatefulValue.nullInstance())); + } + + public void testOf_ThrowsWhenNull() { + expectThrows(NullPointerException.class, () -> StatefulValue.of((String) null)); + } + + public void testOf_ReturnsNewInstanceWithValue() { + var value = randomAlphaOfLength(10); + var statefulValue = StatefulValue.of(value); + assertTrue(statefulValue.isPresent()); + assertThat(statefulValue.get(), is(value)); + } + + public void testIsUndefined_WhenUndefined() { + assertTrue(StatefulValue.undefined().isUndefined()); + } + + public void testIsUndefined_WhenNull() { + assertFalse(StatefulValue.nullInstance().isUndefined()); + } + + public void testIsUndefined_WhenWithValue() { + assertFalse(StatefulValue.of(VALUE).isUndefined()); + } + + public void testIsNull_WhenUndefined() { + assertFalse(StatefulValue.undefined().isNull()); + } + + public void testIsNull_WhenNull() { + assertTrue(StatefulValue.nullInstance().isNull()); + } + + public void testIsNull_WhenWithValue() { + assertFalse(StatefulValue.of(VALUE).isNull()); + } + + public void testIsPresent_WhenUndefined() { + assertFalse(StatefulValue.undefined().isPresent()); + } + + public void testIsPresent_WhenNull() { + assertFalse(StatefulValue.nullInstance().isPresent()); + } + + public void testIsPresent_WhenWithValue() { + assertTrue(StatefulValue.of(VALUE).isPresent()); + } + + public void testGet_ReturnsValueWhenPresent() { + var value = randomAlphaOfLength(10); + assertThat(StatefulValue.of(value).get(), is(value)); + } + + public void testGet_ThrowsWhenUndefined() { + var e = expectThrows(NoSuchElementException.class, () -> StatefulValue.undefined().get()); + assertThat(e.getMessage(), is(NO_VALUE_PRESENT.getMessage())); + } + + public void testGet_ThrowsWhenNull() { + var e = expectThrows(NoSuchElementException.class, () -> StatefulValue.nullInstance().get()); + assertThat(e.getMessage(), is(NO_VALUE_PRESENT.getMessage())); + } + + public void testOrElse_ReturnsValueWhenPresent() { + var value = randomAlphaOfLength(10); + var other = randomAlphaOfLength(10); + assertThat(StatefulValue.of(value).orElse(other), is(value)); + } + + public void testOrElse_ReturnsOtherWhenUndefined() { + var other = randomAlphaOfLength(10); + assertThat(StatefulValue.undefined().orElse(other), is(other)); + } + + public void testOrElse_ReturnsOtherWhenNull() { + var other = randomAlphaOfLength(10); + assertThat(StatefulValue.nullInstance().orElse(other), is(other)); + } + + public void testEquals_hashCode() { + { + var map = new HashMap<>(Map.of(randomAlphaOfLength(10), randomAlphaOfLength(10))); + var equalMap = new HashMap<>(map); + assertEquals(StatefulValue.of(map), StatefulValue.of(equalMap)); + assertEquals(StatefulValue.of(map).hashCode(), StatefulValue.of(equalMap).hashCode()); + } + { + assertEquals(StatefulValue.undefined().hashCode(), StatefulValue.undefined().hashCode()); + assertEquals(StatefulValue.nullInstance().hashCode(), StatefulValue.nullInstance().hashCode()); + } + } + + public void testEquals_WhenPresentWithDifferentValues() { + assertNotEquals(StatefulValue.of("a"), StatefulValue.of("b")); + } + + public void testEquals_WhenDifferentStates() { + assertNotEquals(StatefulValue.undefined(), StatefulValue.nullInstance()); + assertNotEquals(StatefulValue.undefined(), StatefulValue.of(VALUE)); + assertNotEquals(StatefulValue.nullInstance(), StatefulValue.of(VALUE)); + } + + public void testSerializationRoundtrip_WhenUndefined() throws IOException { + var original = StatefulValue.undefined(); + var copy = roundtrip(original); + assertThat(copy, sameInstance(original)); + } + + public void testSerializationRoundtrip_WhenNull() throws IOException { + var original = StatefulValue.nullInstance(); + var copy = roundtrip(original); + assertThat(copy, sameInstance(original)); + } + + public void testSerializationRoundtrip_WhenPresent() throws IOException { + var value = randomAlphaOfLength(10); + var original = StatefulValue.of(value); + var copy = roundtrip(original); + assertThat(copy, is(original)); + assertTrue(copy.isPresent()); + assertThat(copy.get(), is(value)); + } + + private static StatefulValue roundtrip(StatefulValue original) throws IOException { + try (BytesStreamOutput out = new BytesStreamOutput()) { + StatefulValue.write(out, original, StreamOutput::writeString); + try (StreamInput in = out.bytes().streamInput()) { + return StatefulValue.read(in, StreamInput::readString); + } + } + } +} diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/ServiceUtilsTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/ServiceUtilsTests.java index 21af8f7199cc9..30f45216b86e0 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/ServiceUtilsTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/ServiceUtilsTests.java @@ -898,7 +898,7 @@ public void testValidateMapValues_ThrowsException_WhenMapContainsInvalidTypes() exception.getMessage(), is( "Validation Failed: 1: Map field [setting] has an entry that is not valid, " - + "[num_key => 1]. Value type of [1] is not one of [String].;" + + "[num_key => 1]. Value type of [Integer] is not one of [String].;" ) ); } @@ -958,7 +958,7 @@ public void testValidateMapStringValues_ThrowsException_WhenMapContainsInvalidTy exception.getMessage(), is( "Validation Failed: 1: Map field [setting] has an entry that is not valid, " - + "[num_key => 1]. Value type of [1] is not one of [String].;" + + "[num_key => 1]. Value type of [Integer] is not one of [String].;" ) ); } diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiServiceTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiServiceTests.java index ee7b66ecf7ce9..050088ae4987c 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiServiceTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiServiceTests.java @@ -44,6 +44,7 @@ import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xcontent.ToXContent; import org.elasticsearch.xcontent.XContentFactory; +import org.elasticsearch.xcontent.XContentParseException; import org.elasticsearch.xcontent.XContentType; import org.elasticsearch.xpack.core.inference.action.InferenceAction; import org.elasticsearch.xpack.core.inference.results.ChunkedInferenceEmbedding; @@ -90,10 +91,10 @@ import static org.elasticsearch.xpack.inference.services.SenderServiceTests.createMockSender; import static org.elasticsearch.xpack.inference.services.ServiceComponentsTests.createWithEmptySettings; import static org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiSecretSettingsTests.getAzureOpenAiSecretSettingsMap; +import static org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiTaskSettingsTests.createRequestTaskSettingsMap; import static org.elasticsearch.xpack.inference.services.azureopenai.completion.AzureOpenAiCompletionModelTests.createChatCompletionModel; import static org.elasticsearch.xpack.inference.services.azureopenai.embeddings.AzureOpenAiEmbeddingsServiceSettingsTests.getPersistentAzureOpenAiServiceSettingsMap; import static org.elasticsearch.xpack.inference.services.azureopenai.embeddings.AzureOpenAiEmbeddingsServiceSettingsTests.getRequestAzureOpenAiServiceSettingsMap; -import static org.elasticsearch.xpack.inference.services.azureopenai.embeddings.AzureOpenAiEmbeddingsTaskSettingsTests.getAzureOpenAiRequestTaskSettingsMap; import static org.elasticsearch.xpack.inference.services.azureopenai.request.AzureOpenAiUtils.API_KEY_HEADER; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.containsString; @@ -147,7 +148,7 @@ public void testParseRequestConfig_CreatesAnOpenAiEmbeddingsModel() throws IOExc assertThat(embeddingsModel.getServiceSettings().deploymentId(), is(DEPLOYMENT_ID_VALUE)); assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is(API_KEY_VALUE)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); }, exception -> fail("Unexpected exception: " + exception)); service.parseRequestConfig( @@ -155,7 +156,7 @@ public void testParseRequestConfig_CreatesAnOpenAiEmbeddingsModel() throws IOExc TaskType.TEXT_EMBEDDING, getRequestConfigMap( getRequestAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, null, null), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), getAzureOpenAiSecretSettingsMap(API_KEY_VALUE, null) ), modelVerificationListener @@ -173,7 +174,7 @@ public void testParseRequestConfig_CreatesAnOpenAiEmbeddingsModelWhenChunkingSet assertThat(embeddingsModel.getServiceSettings().deploymentId(), is(DEPLOYMENT_ID_VALUE)); assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is(API_KEY_VALUE)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertThat(embeddingsModel.getConfigurations().getChunkingSettings(), instanceOf(ChunkingSettings.class)); }, exception -> fail("Unexpected exception: " + exception)); @@ -182,7 +183,7 @@ public void testParseRequestConfig_CreatesAnOpenAiEmbeddingsModelWhenChunkingSet TaskType.TEXT_EMBEDDING, getRequestConfigMap( getRequestAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, null, null), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), createRandomChunkingSettingsMap(), getAzureOpenAiSecretSettingsMap(API_KEY_VALUE, null) ), @@ -201,7 +202,7 @@ public void testParseRequestConfig_CreatesAnOpenAiEmbeddingsModelWhenChunkingSet assertThat(embeddingsModel.getServiceSettings().deploymentId(), is(DEPLOYMENT_ID_VALUE)); assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is(API_KEY_VALUE)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertThat(embeddingsModel.getConfigurations().getChunkingSettings(), instanceOf(ChunkingSettings.class)); }, exception -> fail("Unexpected exception: " + exception)); @@ -210,7 +211,7 @@ public void testParseRequestConfig_CreatesAnOpenAiEmbeddingsModelWhenChunkingSet TaskType.TEXT_EMBEDDING, getRequestConfigMap( getRequestAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, null, null), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), getAzureOpenAiSecretSettingsMap(API_KEY_VALUE, null) ), modelVerificationListener @@ -233,7 +234,7 @@ public void testParseRequestConfig_ThrowsUnsupportedModelType() throws IOExcepti TaskType.SPARSE_EMBEDDING, getRequestConfigMap( getRequestAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, null, null), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), getAzureOpenAiSecretSettingsMap(API_KEY_VALUE, null) ), modelVerificationListener @@ -245,7 +246,7 @@ public void testParseRequestConfig_ThrowsWhenAnExtraKeyExistsInConfig() throws I try (var service = createAzureOpenAiService()) { var config = getRequestConfigMap( getRequestAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, null, null), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), getAzureOpenAiSecretSettingsMap(API_KEY_VALUE, null) ); config.put("extra_key", "value"); @@ -278,7 +279,7 @@ public void testParseRequestConfig_ThrowsWhenAnExtraKeyExistsInServiceSettingsMa var config = getRequestConfigMap( serviceSettings, - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), getAzureOpenAiSecretSettingsMap(API_KEY_VALUE, null) ); @@ -295,7 +296,7 @@ public void testParseRequestConfig_ThrowsWhenAnExtraKeyExistsInServiceSettingsMa public void testParseRequestConfig_ThrowsWhenAnExtraKeyExistsInTaskSettingsMap() throws IOException { try (var service = createAzureOpenAiService()) { - var taskSettingsMap = getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE); + var taskSettingsMap = createRequestTaskSettingsMap(ROLE_VALUE); taskSettingsMap.put("extra_key", "value"); var config = getRequestConfigMap( @@ -307,8 +308,8 @@ public void testParseRequestConfig_ThrowsWhenAnExtraKeyExistsInTaskSettingsMap() ActionListener modelVerificationListener = ActionListener.wrap((model) -> { fail("Expected exception, but got model: " + model); }, e -> { - assertThat(e, instanceOf(ElasticsearchStatusException.class)); - assertThat(e.getMessage(), is("Configuration contains settings [{extra_key=value}] unknown to the [azureopenai] service")); + assertThat(e, instanceOf(XContentParseException.class)); + assertThat(e.getMessage(), containsString("unknown field [extra_key]")); }); service.parseRequestConfig(INFERENCE_ENTITY_ID_VALUE, TaskType.TEXT_EMBEDDING, config, modelVerificationListener); @@ -322,7 +323,7 @@ public void testParseRequestConfig_ThrowsWhenAnExtraKeyExistsInSecretSettingsMap var config = getRequestConfigMap( getRequestAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, null, null), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), secretSettingsMap ); @@ -347,7 +348,7 @@ public void testParseRequestConfig_MovesModel() throws IOException { assertThat(embeddingsModel.getServiceSettings().deploymentId(), is(DEPLOYMENT_ID_VALUE)); assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is(API_KEY_VALUE)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); }, exception -> fail("Unexpected exception: " + exception)); service.parseRequestConfig( @@ -355,7 +356,7 @@ public void testParseRequestConfig_MovesModel() throws IOException { TaskType.TEXT_EMBEDDING, getRequestConfigMap( getRequestAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, null, null), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), getAzureOpenAiSecretSettingsMap(API_KEY_VALUE, null) ), modelVerificationListener @@ -367,7 +368,7 @@ public void testParsePersistedConfig_WithSecrets_CreatesAnAzureOpenAiEmbeddingsM try (var service = createAzureOpenAiService()) { var persistedConfig = getPersistedConfigMap( getPersistentAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, 100, 512), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), getAzureOpenAiSecretSettingsMap(API_KEY_VALUE, null) ); @@ -389,7 +390,7 @@ public void testParsePersistedConfig_WithSecrets_CreatesAnAzureOpenAiEmbeddingsM assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); assertThat(embeddingsModel.getServiceSettings().dimensions(), is(100)); assertThat(embeddingsModel.getServiceSettings().maxInputTokens(), is(512)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is(API_KEY_VALUE)); } } @@ -398,7 +399,7 @@ public void testParsePersistedConfig_WithSecrets_CreatesAnOpenAiEmbeddingsModelW try (var service = createAzureOpenAiService()) { var persistedConfig = getPersistedConfigMap( getPersistentAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, 100, 512), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), createRandomChunkingSettingsMap(), getAzureOpenAiSecretSettingsMap(API_KEY_VALUE, null) ); @@ -421,7 +422,7 @@ public void testParsePersistedConfig_WithSecrets_CreatesAnOpenAiEmbeddingsModelW assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); assertThat(embeddingsModel.getServiceSettings().dimensions(), is(100)); assertThat(embeddingsModel.getServiceSettings().maxInputTokens(), is(512)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertThat(embeddingsModel.getConfigurations().getChunkingSettings(), instanceOf(ChunkingSettings.class)); assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is(API_KEY_VALUE)); } @@ -431,7 +432,7 @@ public void testParsePersistedConfig_WithSecrets_CreatesAnOpenAiEmbeddingsModelW try (var service = createAzureOpenAiService()) { var persistedConfig = getPersistedConfigMap( getPersistentAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, 100, 512), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), getAzureOpenAiSecretSettingsMap(API_KEY_VALUE, null) ); @@ -453,7 +454,7 @@ public void testParsePersistedConfig_WithSecrets_CreatesAnOpenAiEmbeddingsModelW assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); assertThat(embeddingsModel.getServiceSettings().dimensions(), is(100)); assertThat(embeddingsModel.getServiceSettings().maxInputTokens(), is(512)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertThat(embeddingsModel.getConfigurations().getChunkingSettings(), instanceOf(ChunkingSettings.class)); assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is(API_KEY_VALUE)); } @@ -463,7 +464,7 @@ public void testParsePersistedConfig_WithSecrets_ThrowsErrorTryingToParseInvalid try (var service = createAzureOpenAiService()) { var persistedConfig = getPersistedConfigMap( getPersistentAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, null, null), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), getAzureOpenAiSecretSettingsMap(API_KEY_VALUE, null) ); @@ -495,7 +496,7 @@ public void testParsePersistedConfig_WithSecrets_DoesNotThrowWhenAnExtraKeyExist try (var service = createAzureOpenAiService()) { var persistedConfig = getPersistedConfigMap( getPersistentAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, 100, 512), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), getAzureOpenAiSecretSettingsMap(API_KEY_VALUE, null) ); persistedConfig.config().put("extra_key", "value"); @@ -518,7 +519,7 @@ public void testParsePersistedConfig_WithSecrets_DoesNotThrowWhenAnExtraKeyExist assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); assertThat(embeddingsModel.getServiceSettings().dimensions(), is(100)); assertThat(embeddingsModel.getServiceSettings().maxInputTokens(), is(512)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is(API_KEY_VALUE)); } } @@ -530,7 +531,7 @@ public void testParsePersistedConfig_WithSecrets_DoesNotThrowWhenAnExtraKeyExist var persistedConfig = getPersistedConfigMap( getPersistentAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, 100, 512), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), secretSettingsMap ); @@ -552,7 +553,7 @@ public void testParsePersistedConfig_WithSecrets_DoesNotThrowWhenAnExtraKeyExist assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); assertThat(embeddingsModel.getServiceSettings().dimensions(), is(100)); assertThat(embeddingsModel.getServiceSettings().maxInputTokens(), is(512)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is(API_KEY_VALUE)); } } @@ -561,7 +562,7 @@ public void testParsePersistedConfig_WithSecrets_NotThrowWhenAnExtraKeyExistsInS try (var service = createAzureOpenAiService()) { var persistedConfig = getPersistedConfigMap( getPersistentAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, 100, 512), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), getAzureOpenAiSecretSettingsMap(API_KEY_VALUE, null) ); persistedConfig.secrets().put("extra_key", "value"); @@ -584,7 +585,7 @@ public void testParsePersistedConfig_WithSecrets_NotThrowWhenAnExtraKeyExistsInS assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); assertThat(embeddingsModel.getServiceSettings().dimensions(), is(100)); assertThat(embeddingsModel.getServiceSettings().maxInputTokens(), is(512)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is(API_KEY_VALUE)); } } @@ -602,7 +603,7 @@ public void testParsePersistedConfig_WithSecrets_NotThrowWhenAnExtraKeyExistsInS var persistedConfig = getPersistedConfigMap( serviceSettingsMap, - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), getAzureOpenAiSecretSettingsMap(API_KEY_VALUE, null) ); @@ -624,14 +625,14 @@ public void testParsePersistedConfig_WithSecrets_NotThrowWhenAnExtraKeyExistsInS assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); assertThat(embeddingsModel.getServiceSettings().dimensions(), is(100)); assertThat(embeddingsModel.getServiceSettings().maxInputTokens(), is(512)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is(API_KEY_VALUE)); } } public void testParsePersistedConfig_WithSecrets_NotThrowWhenAnExtraKeyExistsInTaskSettings() throws IOException { try (var service = createAzureOpenAiService()) { - var taskSettingsMap = getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE); + var taskSettingsMap = createRequestTaskSettingsMap(ROLE_VALUE); taskSettingsMap.put("extra_key", "value"); var persistedConfig = getPersistedConfigMap( @@ -658,7 +659,7 @@ public void testParsePersistedConfig_WithSecrets_NotThrowWhenAnExtraKeyExistsInT assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); assertThat(embeddingsModel.getServiceSettings().dimensions(), is(100)); assertThat(embeddingsModel.getServiceSettings().maxInputTokens(), is(512)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is(API_KEY_VALUE)); } } @@ -667,7 +668,7 @@ public void testParsePersistedConfig_CreatesAnAzureOpenAiEmbeddingsModel() throw try (var service = createAzureOpenAiService()) { var persistedConfig = getPersistedConfigMap( getPersistentAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, null, null), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE) + createRequestTaskSettingsMap(ROLE_VALUE) ); var model = service.parsePersistedConfig( @@ -686,7 +687,7 @@ public void testParsePersistedConfig_CreatesAnAzureOpenAiEmbeddingsModel() throw assertThat(embeddingsModel.getServiceSettings().resourceName(), is(RESOURCE_NAME_VALUE)); assertThat(embeddingsModel.getServiceSettings().deploymentId(), is(DEPLOYMENT_ID_VALUE)); assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertNull(embeddingsModel.getSecretSettings()); } } @@ -695,7 +696,7 @@ public void testParsePersistedConfig_CreatesAnAzureOpenAiEmbeddingsModelWhenChun try (var service = createAzureOpenAiService()) { var persistedConfig = getPersistedConfigMap( getPersistentAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, null, null), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE), + createRequestTaskSettingsMap(ROLE_VALUE), createRandomChunkingSettingsMap() ); @@ -715,7 +716,7 @@ public void testParsePersistedConfig_CreatesAnAzureOpenAiEmbeddingsModelWhenChun assertThat(embeddingsModel.getServiceSettings().resourceName(), is(RESOURCE_NAME_VALUE)); assertThat(embeddingsModel.getServiceSettings().deploymentId(), is(DEPLOYMENT_ID_VALUE)); assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertThat(embeddingsModel.getConfigurations().getChunkingSettings(), instanceOf(ChunkingSettings.class)); assertNull(embeddingsModel.getSecretSettings()); } @@ -725,7 +726,7 @@ public void testParsePersistedConfig_CreatesAnOpenAiEmbeddingsModelWhenChunkingS try (var service = createAzureOpenAiService()) { var persistedConfig = getPersistedConfigMap( getPersistentAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, null, null), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE) + createRequestTaskSettingsMap(ROLE_VALUE) ); var model = service.parsePersistedConfig( @@ -744,7 +745,7 @@ public void testParsePersistedConfig_CreatesAnOpenAiEmbeddingsModelWhenChunkingS assertThat(embeddingsModel.getServiceSettings().resourceName(), is(RESOURCE_NAME_VALUE)); assertThat(embeddingsModel.getServiceSettings().deploymentId(), is(DEPLOYMENT_ID_VALUE)); assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertThat(embeddingsModel.getConfigurations().getChunkingSettings(), instanceOf(ChunkingSettings.class)); assertNull(embeddingsModel.getSecretSettings()); } @@ -754,7 +755,7 @@ public void testParsePersistedConfig_ThrowsErrorTryingToParseInvalidModel() thro try (var service = createAzureOpenAiService()) { var persistedConfig = getPersistedConfigMap( getPersistentAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, null, null), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE) + createRequestTaskSettingsMap(ROLE_VALUE) ); var thrownException = expectThrows( @@ -785,7 +786,7 @@ public void testParsePersistedConfig_DoesNotThrowWhenAnExtraKeyExistsInConfig() try (var service = createAzureOpenAiService()) { var persistedConfig = getPersistedConfigMap( getPersistentAzureOpenAiServiceSettingsMap(RESOURCE_NAME_VALUE, DEPLOYMENT_ID_VALUE, API_VERSION_VALUE, null, null), - getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE) + createRequestTaskSettingsMap(ROLE_VALUE) ); persistedConfig.config().put("extra_key", "value"); @@ -805,7 +806,7 @@ public void testParsePersistedConfig_DoesNotThrowWhenAnExtraKeyExistsInConfig() assertThat(embeddingsModel.getServiceSettings().resourceName(), is(RESOURCE_NAME_VALUE)); assertThat(embeddingsModel.getServiceSettings().deploymentId(), is(DEPLOYMENT_ID_VALUE)); assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertNull(embeddingsModel.getSecretSettings()); } } @@ -821,7 +822,7 @@ public void testParsePersistedConfig_NotThrowWhenAnExtraKeyExistsInServiceSettin ); serviceSettingsMap.put("extra_key", "value"); - var persistedConfig = getPersistedConfigMap(serviceSettingsMap, getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE)); + var persistedConfig = getPersistedConfigMap(serviceSettingsMap, createRequestTaskSettingsMap(ROLE_VALUE)); var model = service.parsePersistedConfig( new UnparsedModel( @@ -839,14 +840,14 @@ public void testParsePersistedConfig_NotThrowWhenAnExtraKeyExistsInServiceSettin assertThat(embeddingsModel.getServiceSettings().resourceName(), is(RESOURCE_NAME_VALUE)); assertThat(embeddingsModel.getServiceSettings().deploymentId(), is(DEPLOYMENT_ID_VALUE)); assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertNull(embeddingsModel.getSecretSettings()); } } public void testParsePersistedConfig_NotThrowWhenAnExtraKeyExistsInTaskSettings() throws IOException { try (var service = createAzureOpenAiService()) { - var taskSettingsMap = getAzureOpenAiRequestTaskSettingsMap(ROLE_VALUE); + var taskSettingsMap = createRequestTaskSettingsMap(ROLE_VALUE); taskSettingsMap.put("extra_key", "value"); var persistedConfig = getPersistedConfigMap( @@ -870,7 +871,7 @@ public void testParsePersistedConfig_NotThrowWhenAnExtraKeyExistsInTaskSettings( assertThat(embeddingsModel.getServiceSettings().resourceName(), is(RESOURCE_NAME_VALUE)); assertThat(embeddingsModel.getServiceSettings().deploymentId(), is(DEPLOYMENT_ID_VALUE)); assertThat(embeddingsModel.getServiceSettings().apiVersion(), is(API_VERSION_VALUE)); - assertThat(embeddingsModel.getTaskSettings().user(), is(ROLE_VALUE)); + assertThat(embeddingsModel.getTaskSettings().user().get(), is(ROLE_VALUE)); assertNull(embeddingsModel.getSecretSettings()); } } diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiTaskSettingsTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiTaskSettingsTests.java new file mode 100644 index 0000000000000..397c4d4c52e09 --- /dev/null +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiTaskSettingsTests.java @@ -0,0 +1,415 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.inference.services.azureopenai; + +import org.elasticsearch.TransportVersion; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.ValidationException; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.core.Nullable; +import org.elasticsearch.xcontent.ToXContent; +import org.elasticsearch.xcontent.XContentBuilder; +import org.elasticsearch.xcontent.XContentParseException; +import org.elasticsearch.xcontent.json.JsonXContent; +import org.elasticsearch.xpack.core.ml.AbstractBWCWireSerializationTestCase; +import org.elasticsearch.xpack.inference.common.parser.Headers; +import org.elasticsearch.xpack.inference.common.parser.HeadersTests; +import org.elasticsearch.xpack.inference.common.parser.StatefulValue; +import org.elasticsearch.xpack.inference.services.ConfigurationParseContext; +import org.elasticsearch.xpack.inference.services.openai.OpenAiServiceFields; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiTaskSettings.INFERENCE_AZURE_OPENAI_TASK_SETTINGS_HEADERS; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.sameInstance; + +public abstract class AzureOpenAiTaskSettingsTests> extends AbstractBWCWireSerializationTestCase { + + private static final String USER = "user"; + private static final StatefulValue STATEFUL_USER = StatefulValue.of(USER); + private static final Map HEADERS_MAP = Map.of("key", "value"); + private static final Headers HEADERS = new Headers(StatefulValue.of(HEADERS_MAP)); + + public T createRandom() { + StatefulValue user = randomFrom( + StatefulValue.undefined(), + StatefulValue.nullInstance(), + StatefulValue.of(randomAlphaOfLength(15)) + ); + var headers = HeadersTests.createRandom(); + return create(user, headers); + } + + public void testIsEmpty() { + var bothNull = create(StatefulValue.nullInstance(), Headers.NULL_INSTANCE); + assertTrue(bothNull.isEmpty()); + + var nullUserEmptyHeaders = create(StatefulValue.nullInstance(), new Headers(StatefulValue.of(Map.of()))); + assertTrue(nullUserEmptyHeaders.isEmpty()); + + var nullHeaders = create(STATEFUL_USER, Headers.NULL_INSTANCE); + assertFalse(nullHeaders.isEmpty()); + + var nullUser = create(StatefulValue.nullInstance(), HEADERS); + assertFalse(nullUser.isEmpty()); + + var neitherNull = create(STATEFUL_USER, HEADERS); + assertFalse(neitherNull.isEmpty()); + + var emptyUserString = create(StatefulValue.of(""), Headers.NULL_INSTANCE); + assertTrue(emptyUserString.isEmpty()); + + var headersNull = create(StatefulValue.nullInstance(), Headers.NULL_INSTANCE); + assertTrue(headersNull.isEmpty()); + + var headersUndefined = create(StatefulValue.nullInstance(), Headers.UNDEFINED_INSTANCE); + assertTrue(headersUndefined.isEmpty()); + } + + public void testUpdatedTaskSettings() { + var initialSettings = createRandom(); + var newSettings = createRandom(); + + Map newSettingsMap = new HashMap<>(); + + if (newSettings.user().isUndefined() == false) { + newSettingsMap.put(AzureOpenAiServiceFields.USER, newSettings.user().orElse(null)); + } + + if (newSettings.headers().mapValue().isUndefined() == false) { + newSettingsMap.put(Headers.HEADERS_FIELD, newSettings.headers().mapValue().orElse(null)); + } + + var updatedSettings = initialSettings.updatedTaskSettings(Collections.unmodifiableMap(newSettingsMap)); + + if (newSettings.user().isPresent()) { + assertEquals(newSettings.user(), updatedSettings.user()); + } else if (newSettings.user().isNull()) { + // When the new settings has a null user, we want to remove the existing user, so the updated settings should now + // have the user as undefined + assertEquals(StatefulValue.undefined(), updatedSettings.user()); + } else { + // If the new settings did not have user, the updated settings should keep the existing user + assertEquals(initialSettings.user(), updatedSettings.user()); + } + + if (newSettings.headers().isPresent()) { + assertEquals(newSettings.headers(), updatedSettings.headers()); + } else if (newSettings.headers().isNull()) { + // When the new settings has a null headers field, we want to remove the existing headers, so the updated settings should now + // have the headers as undefined + assertEquals(Headers.UNDEFINED_INSTANCE, updatedSettings.headers()); + } else { + // If the new settings did not have the headers field, the updated settings should keep the existing headers + assertEquals(initialSettings.headers(), updatedSettings.headers()); + } + } + + public void testUpdatedTaskSettings_ApplyingEmptyHeaders() { + var initialSettings = create(STATEFUL_USER, Headers.NULL_INSTANCE); + Map newSettingsMap = Map.of(Headers.HEADERS_FIELD, Map.of()); + + var updatedSettings = initialSettings.updatedTaskSettings(newSettingsMap); + assertThat(updatedSettings, is(create(STATEFUL_USER, Headers.UNDEFINED_INSTANCE))); + + var initialSettingsDefinedHeaders = create(STATEFUL_USER, HEADERS); + // This will remove the headers because using "headers": {} in the update counts as the user wanting to remove all existing headers + updatedSettings = initialSettingsDefinedHeaders.updatedTaskSettings(newSettingsMap); + assertThat(updatedSettings, is(create(STATEFUL_USER, Headers.UNDEFINED_INSTANCE))); + } + + public void testUpdateTaskSettings_EmptyInstance() { + var initialSettings = create(STATEFUL_USER, HEADERS); + var newSettingsMap = new HashMap(); + newSettingsMap.put(AzureOpenAiServiceFields.USER, null); + newSettingsMap.put(Headers.HEADERS_FIELD, null); + + var updatedSettings = initialSettings.updatedTaskSettings(newSettingsMap); + assertThat(updatedSettings, sameInstance(emptySettings())); + } + + public void testFromMap_WithUserAndHeaders() { + assertThat( + createFromMap( + new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, USER, Headers.HEADERS_FIELD, HEADERS_MAP)), + ConfigurationParseContext.REQUEST + ), + is(create(STATEFUL_USER, HEADERS)) + ); + } + + public void testFromMap_UserIsEmptyString() { + var thrownException = expectThrows( + ValidationException.class, + () -> createFromMap(new HashMap<>(Map.of(OpenAiServiceFields.USER, "")), ConfigurationParseContext.REQUEST) + ); + + assertThat( + thrownException.getMessage(), + is(Strings.format("Validation Failed: 1: [task_settings] Invalid value empty string. [user] must be a non-empty string;")) + ); + } + + public void testFromMap_UserIsEmptyString_DoesNotThrowForPersistentContext() { + var settings = createFromMap(new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, "")), ConfigurationParseContext.PERSISTENT); + assertTrue(settings.user().isPresent() && settings.user().get().isEmpty()); + } + + public void testFromMap_isEmpty() { + { + var emptyMap = createFromMap(new HashMap<>(Map.of()), randomContext()); + assertTrue(emptyMap.isEmpty()); + } + { + var emptyUserUndefinedHeaders = createFromMap( + new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, "")), + ConfigurationParseContext.PERSISTENT + ); + assertTrue(emptyUserUndefinedHeaders.isEmpty()); + } + { + var emptyUserEmptyHeaders = createFromMap( + new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, "", Headers.HEADERS_FIELD, Map.of())), + ConfigurationParseContext.PERSISTENT + ); + assertTrue(emptyUserEmptyHeaders.isEmpty()); + } + { + var emptyUserNullHeadersMap = new HashMap(); + emptyUserNullHeadersMap.put(AzureOpenAiServiceFields.USER, ""); + emptyUserNullHeadersMap.put(Headers.HEADERS_FIELD, null); + var emptyUserNullHeaders = createFromMap(emptyUserNullHeadersMap, ConfigurationParseContext.PERSISTENT); + assertTrue(emptyUserNullHeaders.isEmpty()); + } + { + var undefinedUserEmptyHeaders = createFromMap(new HashMap<>(Map.of(Headers.HEADERS_FIELD, Map.of())), randomContext()); + assertTrue(undefinedUserEmptyHeaders.isEmpty()); + } + { + var nullUserNullHeadersMap = new HashMap(); + nullUserNullHeadersMap.put(AzureOpenAiServiceFields.USER, null); + nullUserNullHeadersMap.put(Headers.HEADERS_FIELD, null); + var emptyUserNullHeaders = createFromMap(nullUserNullHeadersMap, randomContext()); + assertTrue(emptyUserNullHeaders.isEmpty()); + } + } + + private static ConfigurationParseContext randomContext() { + return randomBoolean() ? ConfigurationParseContext.REQUEST : ConfigurationParseContext.PERSISTENT; + } + + public void testFromMap_MissingUser_DoesNotThrowException() { + var taskSettings = createFromMap(new HashMap<>(Map.of()), ConfigurationParseContext.REQUEST); + assertTrue(taskSettings.user().isUndefined()); + } + + public void testFromMap_ReturnsEmptySettings_WhenTheMapDoesNotContainTheFields() { + // The HashMap is missing the headers key + var settings = createFromMap(new HashMap<>(HEADERS_MAP), ConfigurationParseContext.PERSISTENT); + assertTrue(settings.user().isUndefined()); + assertThat(settings.headers(), sameInstance(Headers.UNDEFINED_INSTANCE)); + } + + public void testFromMap_ParsesCorrectly_WhenUserIsMissing() { + var settings = createFromMap( + new HashMap<>(Map.of(Headers.HEADERS_FIELD, new HashMap<>(HEADERS_MAP))), + ConfigurationParseContext.REQUEST + ); + + assertTrue(settings.user().isUndefined()); + assertThat(settings.headers(), is(HEADERS)); + } + + public void testFromMap_ParsesCorrectly_WhenHeadersIsMissing() { + var settings = createFromMap(new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, USER)), ConfigurationParseContext.REQUEST); + + assertTrue(settings.user().isPresent()); + assertThat(settings.user().get(), is(USER)); + assertThat(settings.headers(), is(Headers.UNDEFINED_INSTANCE)); + } + + public void testFromMap_ParsesCorrectly_WhenHeadersIsEmptyMap() { + var settings = createFromMap( + new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, USER, Headers.HEADERS_FIELD, Map.of())), + ConfigurationParseContext.REQUEST + ); + + assertTrue(settings.user().isPresent()); + assertThat(settings.user().get(), is(USER)); + assertTrue(settings.headers().isEmpty()); + } + + public void testFromMap_ParsesCorrectly_WhenHeadersMapOfNulls() { + var headersMap = new HashMap(); + headersMap.put("key1", null); + headersMap.put("key2", null); + var settings = createFromMap( + new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, USER, Headers.HEADERS_FIELD, headersMap)), + ConfigurationParseContext.REQUEST + ); + + assertTrue(settings.user().isPresent()); + assertThat(settings.user().get(), is(USER)); + assertTrue(settings.headers().isEmpty()); + } + + public void testFromMap_ThrowsException_WhenHeadersContainsAnInteger() { + var exception = expectThrows( + XContentParseException.class, + () -> createFromMap( + new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, USER, Headers.HEADERS_FIELD, new HashMap<>(Map.of("key", 1)))), + ConfigurationParseContext.REQUEST + ) + ); + + assertThat(exception.getMessage(), containsString("failed to parse field [headers]")); + assertThat( + exception.getCause().getMessage(), + containsString( + "Map field [headers] has an entry that is not valid, [key => 1]. Value type of [Integer] is not one of [String].;" + ) + ); + } + + public void testFromMap_ThrowsException_WhenUserIsAnInteger() { + var exception = expectThrows( + XContentParseException.class, + () -> createFromMap(new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, 1)), ConfigurationParseContext.REQUEST) + ); + + assertThat( + exception.getMessage(), + containsString("[azure_openai_task_settings_parser] user doesn't support values of type: VALUE_NUMBER") + ); + } + + public void testFromMap_WithUser() { + assertThat( + create(STATEFUL_USER, Headers.UNDEFINED_INSTANCE), + is(createFromMap(new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, USER)), ConfigurationParseContext.PERSISTENT)) + ); + } + + public void testFromMap_WithRequestContext_ReturnsEmptySettings_WhenMapIsEmpty() { + var settings = createFromMap(new HashMap<>(Map.of()), ConfigurationParseContext.REQUEST); + assertTrue(settings.isEmpty()); + assertTrue(settings.user().isUndefined()); + assertThat(settings.headers(), sameInstance(Headers.UNDEFINED_INSTANCE)); + assertThat(settings, sameInstance(emptySettings())); + } + + public void testUpdatedTaskSettings_KeepsOriginalValues_WhenOverridesAreEmpty() { + var taskSettings = createFromMap( + new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, USER, Headers.HEADERS_FIELD, HEADERS_MAP)), + ConfigurationParseContext.PERSISTENT + ); + + var overriddenTaskSettings = taskSettings.updatedTaskSettings(Map.of()); + assertThat(overriddenTaskSettings, is(taskSettings)); + } + + public void testToXContent_RoundTrip() throws IOException { + // The reason we don't allow null here is that when a NULL_INSTANCE is serialized to xContent + // it is not written (aka would look like this {}) instead of it being written {"headers": null} or {"user": null}. + // This is because it's only used for the update API to indicate that the existing headers should be removed. + var user = randomFrom(StatefulValue.undefined(), StatefulValue.of(randomAlphaOfLength(15))); + var headers = HeadersTests.createRandomNonNull(); + var original = create(user, headers); + + String json; + try (XContentBuilder builder = XContentBuilder.builder(JsonXContent.jsonXContent)) { + original.toXContent(builder, ToXContent.EMPTY_PARAMS); + json = Strings.toString(builder); + } + var map = XContentHelper.convertToMap(JsonXContent.jsonXContent, json, false); + + var roundTrippedPersistentContext = createFromMap(map, ConfigurationParseContext.PERSISTENT); + assertThat(roundTrippedPersistentContext, is(original)); + + var roundTrippedRequestContext = createFromMap(map, ConfigurationParseContext.REQUEST); + assertThat(roundTrippedRequestContext, is(original)); + } + + public void testFromMap_ThrowsException_WhenMapContainsExtraFields_ForRequestContext() { + var exception = expectThrows( + IllegalArgumentException.class, + () -> createFromMap( + new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, USER, Headers.HEADERS_FIELD, Map.of(), "extra_field", "value")), + ConfigurationParseContext.REQUEST + ) + ); + + assertThat(exception.getMessage(), containsString("[azure_openai_task_settings_parser] unknown field [extra_field]")); + } + + public void testFromMap_DoesNotThrowException_WhenMapContainsExtraFields_ForPersistentContext() { + var settings = createFromMap( + new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, USER, Headers.HEADERS_FIELD, Map.of(), "extra_field", "value")), + ConfigurationParseContext.PERSISTENT + ); + + assertTrue(settings.user().isPresent()); + assertThat(settings.user().get(), is(USER)); + assertTrue(settings.headers().isEmpty()); + } + + public static Map createRequestTaskSettingsMap(@Nullable String user) { + var map = new HashMap(); + + if (user != null) { + map.put(AzureOpenAiServiceFields.USER, user); + } + + return map; + } + + @Override + protected T mutateInstanceForVersion(T instance, TransportVersion version) { + if (version.supports(INFERENCE_AZURE_OPENAI_TASK_SETTINGS_HEADERS)) { + return instance; + } + + var userForCreate = instance.user().isPresent() ? instance.user() : StatefulValue.undefined(); + + return create(userForCreate, Headers.UNDEFINED_INSTANCE); + } + + @Override + protected T mutateInstance(T instance) { + var setNull = randomBoolean(); + var fieldToMutate = randomIntBetween(0, 1); + + return switch (fieldToMutate) { + case 0 -> { + StatefulValue userForCreate; + + if (instance.user().isUndefined()) { + userForCreate = setNull ? StatefulValue.nullInstance() : StatefulValue.of(randomAlphaOfLength(15)); + } else if (instance.user().isNull()) { + userForCreate = randomBoolean() ? StatefulValue.undefined() : StatefulValue.of(randomAlphaOfLength(15)); + } else { + userForCreate = StatefulValue.of(instance.user() + "modified"); + } + yield create(userForCreate, instance.headers()); + } + case 1 -> create(instance.user(), HeadersTests.doMutateInstance(instance.headers())); + default -> throw new IllegalStateException("Unexpected value: " + fieldToMutate); + }; + } + + protected abstract T create(StatefulValue user, @Nullable Headers headers); + + protected abstract T createFromMap(Map map, ConfigurationParseContext context); + + protected abstract T emptySettings(); +} diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/action/AzureOpenAiActionCreatorTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/action/AzureOpenAiActionCreatorTests.java index 23c773ab0d61b..20b6f1741ae46 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/action/AzureOpenAiActionCreatorTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/action/AzureOpenAiActionCreatorTests.java @@ -50,9 +50,9 @@ import static org.elasticsearch.xpack.inference.external.http.retry.RetrySettingsTests.buildSettingsWithRetryFields; import static org.elasticsearch.xpack.inference.external.http.sender.HttpRequestSenderTests.createSender; import static org.elasticsearch.xpack.inference.services.ServiceComponentsTests.createWithEmptySettings; +import static org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiTaskSettingsTests.createRequestTaskSettingsMap; import static org.elasticsearch.xpack.inference.services.azureopenai.completion.AzureOpenAiCompletionModelTests.createCompletionModel; import static org.elasticsearch.xpack.inference.services.azureopenai.embeddings.AzureOpenAiEmbeddingsModelTests.createModel; -import static org.elasticsearch.xpack.inference.services.azureopenai.embeddings.AzureOpenAiEmbeddingsRequestTaskSettingsTests.createRequestTaskSettingsMap; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionModelTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionModelTests.java index be31721314c53..9c62d57f38cfc 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionModelTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionModelTests.java @@ -11,6 +11,8 @@ import org.elasticsearch.core.Nullable; import org.elasticsearch.inference.TaskType; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.inference.common.parser.Headers; +import org.elasticsearch.xpack.inference.common.parser.StatefulValue; import org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiSecretSettings; import org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiServiceFields; @@ -165,13 +167,14 @@ private static AzureOpenAiCompletionModel createAzureOpenAiModelWithTaskType( ) { var secureApiKey = apiKey != null ? new SecureString(apiKey.toCharArray()) : null; var secureEntraId = entraId != null ? new SecureString(entraId.toCharArray()) : null; + var userToUse = user == null ? StatefulValue.undefined() : StatefulValue.of(user); return new AzureOpenAiCompletionModel( inferenceEntityId, taskType, "service", new AzureOpenAiCompletionServiceSettings(resourceName, deploymentId, apiVersion, null), - new AzureOpenAiCompletionTaskSettings(user), + new AzureOpenAiCompletionTaskSettings(userToUse, Headers.UNDEFINED_INSTANCE), new AzureOpenAiSecretSettings(secureApiKey, secureEntraId) ); } diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionRequestTaskSettingsTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionRequestTaskSettingsTests.java deleted file mode 100644 index 51963c275a08a..0000000000000 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionRequestTaskSettingsTests.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.inference.services.azureopenai.completion; - -import org.elasticsearch.common.ValidationException; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiServiceFields; - -import java.util.HashMap; -import java.util.Map; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; - -public class AzureOpenAiCompletionRequestTaskSettingsTests extends ESTestCase { - - public void testFromMap_ReturnsEmptySettings_WhenMapIsEmpty() { - var settings = AzureOpenAiCompletionRequestTaskSettings.fromMap(new HashMap<>(Map.of())); - assertThat(settings, is(AzureOpenAiCompletionRequestTaskSettings.EMPTY_SETTINGS)); - } - - public void testFromMap_ReturnsEmptySettings_WhenMapDoesNotContainKnownFields() { - var settings = AzureOpenAiCompletionRequestTaskSettings.fromMap(new HashMap<>(Map.of("key", "model"))); - assertThat(settings, is(AzureOpenAiCompletionRequestTaskSettings.EMPTY_SETTINGS)); - } - - public void testFromMap_ReturnsUser() { - var settings = AzureOpenAiCompletionRequestTaskSettings.fromMap(new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, "user"))); - assertThat(settings.user(), is("user")); - } - - public void testFromMap_WhenUserIsEmpty_ThrowsValidationException() { - var exception = expectThrows( - ValidationException.class, - () -> AzureOpenAiCompletionRequestTaskSettings.fromMap(new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, ""))) - ); - - assertThat(exception.getMessage(), containsString("[user] must be a non-empty string")); - } -} diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionTaskSettingsTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionTaskSettingsTests.java index 42a5388b66d6b..79fadb90df2ab 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionTaskSettingsTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/completion/AzureOpenAiCompletionTaskSettingsTests.java @@ -7,109 +7,38 @@ package org.elasticsearch.xpack.inference.services.azureopenai.completion; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.ValidationException; import org.elasticsearch.common.io.stream.Writeable; -import org.elasticsearch.test.AbstractWireSerializingTestCase; -import org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiServiceFields; -import org.elasticsearch.xpack.inference.services.azureopenai.embeddings.AzureOpenAiEmbeddingsTaskSettings; -import org.hamcrest.MatcherAssert; +import org.elasticsearch.xpack.inference.common.parser.Headers; +import org.elasticsearch.xpack.inference.common.parser.StatefulValue; +import org.elasticsearch.xpack.inference.services.ConfigurationParseContext; +import org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiTaskSettingsTests; -import java.io.IOException; -import java.util.HashMap; import java.util.Map; -import static org.hamcrest.Matchers.is; +public class AzureOpenAiCompletionTaskSettingsTests extends AzureOpenAiTaskSettingsTests { -public class AzureOpenAiCompletionTaskSettingsTests extends AbstractWireSerializingTestCase { - - public static AzureOpenAiCompletionTaskSettings createRandomWithUser() { - return new AzureOpenAiCompletionTaskSettings(randomAlphaOfLength(15)); - } - - public static AzureOpenAiCompletionTaskSettings createRandom() { - return new AzureOpenAiCompletionTaskSettings(randomAlphaOfLengthOrNull(15)); - } - - public void testIsEmpty() { - var randomSettings = createRandom(); - var stringRep = Strings.toString(randomSettings); - assertEquals(stringRep, randomSettings.isEmpty(), stringRep.equals("{}")); - } - - public void testUpdatedTaskSettings() { - var initialSettings = createRandom(); - var newSettings = createRandom(); - AzureOpenAiCompletionTaskSettings updatedSettings = (AzureOpenAiCompletionTaskSettings) initialSettings.updatedTaskSettings( - newSettings.user() == null ? Map.of() : Map.of(AzureOpenAiServiceFields.USER, newSettings.user()) - ); - - assertEquals(newSettings.user() == null ? initialSettings.user() : newSettings.user(), updatedSettings.user()); - } - - public void testFromMap_WithUser() { - var user = "user"; - - assertThat( - new AzureOpenAiCompletionTaskSettings(user), - is(AzureOpenAiCompletionTaskSettings.fromMap(new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, user)))) - ); - } - - public void testFromMap_UserIsEmptyString() { - var thrownException = expectThrows( - ValidationException.class, - () -> AzureOpenAiEmbeddingsTaskSettings.fromMap(new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, ""))) - ); - - MatcherAssert.assertThat( - thrownException.getMessage(), - is(Strings.format("Validation Failed: 1: [task_settings] Invalid value empty string. [user] must be a non-empty string;")) - ); - } - - public void testFromMap_MissingUser_DoesNotThrowException() { - var taskSettings = AzureOpenAiCompletionTaskSettings.fromMap(new HashMap<>(Map.of())); - assertNull(taskSettings.user()); - } - - public void testOverrideWith_KeepsOriginalValuesWithOverridesAreNull() { - var taskSettings = AzureOpenAiCompletionTaskSettings.fromMap(new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, "user"))); - - var overriddenTaskSettings = AzureOpenAiCompletionTaskSettings.of( - taskSettings, - AzureOpenAiCompletionRequestTaskSettings.EMPTY_SETTINGS - ); - assertThat(overriddenTaskSettings, is(taskSettings)); + @Override + protected Writeable.Reader instanceReader() { + return AzureOpenAiCompletionTaskSettings::new; } - public void testOverrideWith_UsesOverriddenSettings() { - var user = "user"; - var userOverride = "user override"; - - var taskSettings = AzureOpenAiCompletionTaskSettings.fromMap(new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, user))); - - var requestTaskSettings = AzureOpenAiCompletionRequestTaskSettings.fromMap( - new HashMap<>(Map.of(AzureOpenAiServiceFields.USER, userOverride)) - ); - - var overriddenTaskSettings = AzureOpenAiCompletionTaskSettings.of(taskSettings, requestTaskSettings); - assertThat(overriddenTaskSettings, is(new AzureOpenAiCompletionTaskSettings(userOverride))); + @Override + protected AzureOpenAiCompletionTaskSettings createTestInstance() { + return createRandom(); } @Override - protected Writeable.Reader instanceReader() { - return AzureOpenAiCompletionTaskSettings::new; + protected AzureOpenAiCompletionTaskSettings create(StatefulValue user, Headers headers) { + return new AzureOpenAiCompletionTaskSettings(user, headers); } @Override - protected AzureOpenAiCompletionTaskSettings createTestInstance() { - return createRandomWithUser(); + protected AzureOpenAiCompletionTaskSettings createFromMap(Map map, ConfigurationParseContext context) { + return AzureOpenAiCompletionTaskSettings.fromMap(map, context); } @Override - protected AzureOpenAiCompletionTaskSettings mutateInstance(AzureOpenAiCompletionTaskSettings instance) throws IOException { - String user = randomValueOtherThan(instance.user(), () -> randomAlphaOfLengthOrNull(15)); - return new AzureOpenAiCompletionTaskSettings(user); + protected AzureOpenAiCompletionTaskSettings emptySettings() { + return AzureOpenAiCompletionTaskSettings.EMPTY; } } diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsModelTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsModelTests.java index 2f6760cb36e9f..332a65d8c122c 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsModelTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsModelTests.java @@ -13,12 +13,14 @@ import org.elasticsearch.inference.SimilarityMeasure; import org.elasticsearch.inference.TaskType; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.inference.common.parser.Headers; +import org.elasticsearch.xpack.inference.common.parser.StatefulValue; import org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiSecretSettings; import java.net.URISyntaxException; import java.util.Map; -import static org.elasticsearch.xpack.inference.services.azureopenai.embeddings.AzureOpenAiEmbeddingsTaskSettingsTests.getAzureOpenAiRequestTaskSettingsMap; +import static org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiTaskSettingsTests.createRequestTaskSettingsMap; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.sameInstance; @@ -26,7 +28,7 @@ public class AzureOpenAiEmbeddingsModelTests extends ESTestCase { public void testOverrideWith_OverridesUser() { var model = createModel("resource", "deployment", "apiversion", null, "api_key", null, "id"); - var requestTaskSettingsMap = getAzureOpenAiRequestTaskSettingsMap("user_override"); + var requestTaskSettingsMap = createRequestTaskSettingsMap("user_override"); var overriddenModel = AzureOpenAiEmbeddingsModel.of(model, requestTaskSettingsMap); @@ -108,12 +110,14 @@ public static AzureOpenAiEmbeddingsModel createModel( ) { var secureApiKey = apiKey != null ? new SecureString(apiKey.toCharArray()) : null; var secureEntraId = entraId != null ? new SecureString(entraId.toCharArray()) : null; + var userToUse = user == null ? StatefulValue.undefined() : StatefulValue.of(user); + return new AzureOpenAiEmbeddingsModel( inferenceEntityId, TaskType.TEXT_EMBEDDING, "service", new AzureOpenAiEmbeddingsServiceSettings(resourceName, deploymentId, apiVersion, null, false, null, null, null), - new AzureOpenAiEmbeddingsTaskSettings(user), + new AzureOpenAiEmbeddingsTaskSettings(userToUse, Headers.UNDEFINED_INSTANCE), chunkingSettings, new AzureOpenAiSecretSettings(secureApiKey, secureEntraId) ); @@ -130,12 +134,14 @@ public static AzureOpenAiEmbeddingsModel createModel( ) { var secureApiKey = apiKey != null ? new SecureString(apiKey.toCharArray()) : null; var secureEntraId = entraId != null ? new SecureString(entraId.toCharArray()) : null; + var userToUse = user == null ? StatefulValue.undefined() : StatefulValue.of(user); + return new AzureOpenAiEmbeddingsModel( inferenceEntityId, TaskType.TEXT_EMBEDDING, "service", new AzureOpenAiEmbeddingsServiceSettings(resourceName, deploymentId, apiVersion, null, false, null, null, null), - new AzureOpenAiEmbeddingsTaskSettings(user), + new AzureOpenAiEmbeddingsTaskSettings(userToUse, Headers.UNDEFINED_INSTANCE), null, new AzureOpenAiSecretSettings(secureApiKey, secureEntraId) ); @@ -156,6 +162,7 @@ public static AzureOpenAiEmbeddingsModel createModel( ) { var secureApiKey = apiKey != null ? new SecureString(apiKey.toCharArray()) : null; var secureEntraId = entraId != null ? new SecureString(entraId.toCharArray()) : null; + var userToUse = user == null ? StatefulValue.undefined() : StatefulValue.of(user); return new AzureOpenAiEmbeddingsModel( inferenceEntityId, @@ -171,7 +178,7 @@ public static AzureOpenAiEmbeddingsModel createModel( similarity, null ), - new AzureOpenAiEmbeddingsTaskSettings(user), + new AzureOpenAiEmbeddingsTaskSettings(userToUse, Headers.UNDEFINED_INSTANCE), null, new AzureOpenAiSecretSettings(secureApiKey, secureEntraId) ); diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsRequestTaskSettingsTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsRequestTaskSettingsTests.java deleted file mode 100644 index 0aef2a97ee0a1..0000000000000 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsRequestTaskSettingsTests.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.inference.services.azureopenai.embeddings; - -import org.elasticsearch.common.ValidationException; -import org.elasticsearch.core.Nullable; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xpack.inference.services.openai.OpenAiServiceFields; - -import java.util.HashMap; -import java.util.Map; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; - -public class AzureOpenAiEmbeddingsRequestTaskSettingsTests extends ESTestCase { - public void testFromMap_ReturnsEmptySettings_WhenTheMapIsEmpty() { - var settings = AzureOpenAiEmbeddingsRequestTaskSettings.fromMap(new HashMap<>(Map.of())); - assertThat(settings, is(AzureOpenAiEmbeddingsRequestTaskSettings.EMPTY_SETTINGS)); - } - - public void testFromMap_ReturnsEmptySettings_WhenTheMapDoesNotContainTheFields() { - var settings = AzureOpenAiEmbeddingsRequestTaskSettings.fromMap(new HashMap<>(Map.of("key", "model"))); - assertNull(settings.user()); - } - - public void testFromMap_ReturnsUser() { - var settings = AzureOpenAiEmbeddingsRequestTaskSettings.fromMap(new HashMap<>(Map.of(OpenAiServiceFields.USER, "user"))); - assertThat(settings.user(), is("user")); - } - - public void testFromMap_WhenUserIsEmpty_ThrowsValidationException() { - var exception = expectThrows( - ValidationException.class, - () -> AzureOpenAiEmbeddingsRequestTaskSettings.fromMap(new HashMap<>(Map.of(OpenAiServiceFields.USER, ""))) - ); - - assertThat(exception.getMessage(), containsString("[user] must be a non-empty string")); - } - - public static Map createRequestTaskSettingsMap(@Nullable String user) { - var map = new HashMap(); - - if (user != null) { - map.put(OpenAiServiceFields.USER, user); - } - - return map; - } -} diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsTaskSettingsTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsTaskSettingsTests.java index 5e7b40912511b..dddd6319351c7 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsTaskSettingsTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/embeddings/AzureOpenAiEmbeddingsTaskSettingsTests.java @@ -7,95 +7,15 @@ package org.elasticsearch.xpack.inference.services.azureopenai.embeddings; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.ValidationException; import org.elasticsearch.common.io.stream.Writeable; -import org.elasticsearch.core.Nullable; -import org.elasticsearch.test.AbstractWireSerializingTestCase; -import org.hamcrest.MatcherAssert; +import org.elasticsearch.xpack.inference.common.parser.Headers; +import org.elasticsearch.xpack.inference.common.parser.StatefulValue; +import org.elasticsearch.xpack.inference.services.ConfigurationParseContext; +import org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiTaskSettingsTests; -import java.io.IOException; -import java.util.HashMap; import java.util.Map; -import static org.elasticsearch.xpack.inference.services.azureopenai.AzureOpenAiServiceFields.USER; -import static org.hamcrest.Matchers.is; - -public class AzureOpenAiEmbeddingsTaskSettingsTests extends AbstractWireSerializingTestCase { - - public static AzureOpenAiEmbeddingsTaskSettings createRandomWithUser() { - return new AzureOpenAiEmbeddingsTaskSettings(randomAlphaOfLength(15)); - } - - public void testIsEmpty() { - var randomSettings = createRandom(); - var stringRep = Strings.toString(randomSettings); - assertEquals(stringRep, randomSettings.isEmpty(), stringRep.equals("{}")); - } - - /** - * The created settings can have the user set to null. - */ - public static AzureOpenAiEmbeddingsTaskSettings createRandom() { - return new AzureOpenAiEmbeddingsTaskSettings(randomAlphaOfLengthOrNull(15)); - } - - public void testUpdatedTaskSettings() { - var initialSettings = createRandom(); - var newSettings = createRandom(); - AzureOpenAiEmbeddingsTaskSettings updatedSettings = (AzureOpenAiEmbeddingsTaskSettings) initialSettings.updatedTaskSettings( - newSettings.user() == null ? Map.of() : Map.of(USER, newSettings.user()) - ); - - if (newSettings.user() == null) { - assertEquals(initialSettings.user(), updatedSettings.user()); - } else { - assertEquals(newSettings.user(), updatedSettings.user()); - } - } - - public void testFromMap_WithUser() { - assertEquals( - new AzureOpenAiEmbeddingsTaskSettings("user"), - AzureOpenAiEmbeddingsTaskSettings.fromMap(new HashMap<>(Map.of(USER, "user"))) - ); - } - - public void testFromMap_UserIsEmptyString() { - var thrownException = expectThrows( - ValidationException.class, - () -> AzureOpenAiEmbeddingsTaskSettings.fromMap(new HashMap<>(Map.of(USER, ""))) - ); - - MatcherAssert.assertThat( - thrownException.getMessage(), - is(Strings.format("Validation Failed: 1: [task_settings] Invalid value empty string. [user] must be a non-empty string;")) - ); - } - - public void testFromMap_MissingUser_DoesNotThrowException() { - var taskSettings = AzureOpenAiEmbeddingsTaskSettings.fromMap(new HashMap<>(Map.of())); - assertNull(taskSettings.user()); - } - - public void testOverrideWith_KeepsOriginalValuesWithOverridesAreNull() { - var taskSettings = AzureOpenAiEmbeddingsTaskSettings.fromMap(new HashMap<>(Map.of(USER, "user"))); - - var overriddenTaskSettings = AzureOpenAiEmbeddingsTaskSettings.of( - taskSettings, - AzureOpenAiEmbeddingsRequestTaskSettings.EMPTY_SETTINGS - ); - MatcherAssert.assertThat(overriddenTaskSettings, is(taskSettings)); - } - - public void testOverrideWith_UsesOverriddenSettings() { - var taskSettings = AzureOpenAiEmbeddingsTaskSettings.fromMap(new HashMap<>(Map.of(USER, "user"))); - - var requestTaskSettings = AzureOpenAiEmbeddingsRequestTaskSettings.fromMap(new HashMap<>(Map.of(USER, "user2"))); - - var overriddenTaskSettings = AzureOpenAiEmbeddingsTaskSettings.of(taskSettings, requestTaskSettings); - MatcherAssert.assertThat(overriddenTaskSettings, is(new AzureOpenAiEmbeddingsTaskSettings("user2"))); - } +public class AzureOpenAiEmbeddingsTaskSettingsTests extends AzureOpenAiTaskSettingsTests { @Override protected Writeable.Reader instanceReader() { @@ -104,22 +24,21 @@ protected Writeable.Reader instanceReader() { @Override protected AzureOpenAiEmbeddingsTaskSettings createTestInstance() { - return createRandomWithUser(); + return createRandom(); } @Override - protected AzureOpenAiEmbeddingsTaskSettings mutateInstance(AzureOpenAiEmbeddingsTaskSettings instance) throws IOException { - String user = randomValueOtherThan(instance.user(), () -> randomAlphaOfLengthOrNull(15)); - return new AzureOpenAiEmbeddingsTaskSettings(user); + protected AzureOpenAiEmbeddingsTaskSettings create(StatefulValue user, Headers headers) { + return new AzureOpenAiEmbeddingsTaskSettings(user, headers); } - public static Map getAzureOpenAiRequestTaskSettingsMap(@Nullable String user) { - var map = new HashMap(); - - if (user != null) { - map.put(USER, user); - } + @Override + protected AzureOpenAiEmbeddingsTaskSettings createFromMap(Map map, ConfigurationParseContext context) { + return AzureOpenAiEmbeddingsTaskSettings.fromMap(map, context); + } - return map; + @Override + protected AzureOpenAiEmbeddingsTaskSettings emptySettings() { + return AzureOpenAiEmbeddingsTaskSettings.EMPTY; } } diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/custom/CustomServiceSettingsTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/custom/CustomServiceSettingsTests.java index 72a31e6a789f1..d53becee3613a 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/custom/CustomServiceSettingsTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/custom/CustomServiceSettingsTests.java @@ -537,7 +537,7 @@ public void testFromMap_ReturnsError_IfHeadersContainsNonStringValues() { exception.getMessage(), is( "Validation Failed: 1: Map field [headers] has an entry that is not valid, [key => 1]. " - + "Value type of [1] is not one of [String].;" + + "Value type of [Integer] is not one of [String].;" ) ); } diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/custom/CustomTaskSettingsTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/custom/CustomTaskSettingsTests.java index 471a66a642ec8..a499f81a564bc 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/custom/CustomTaskSettingsTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/custom/CustomTaskSettingsTests.java @@ -70,7 +70,7 @@ public void testFromMap_Throws_IfValueIsInvalid() { exception.getMessage(), is( "Validation Failed: 1: Map field [parameters] has an entry that is not valid, [key => {another_key=value}]. " - + "Value type of [{another_key=value}] is not one of [Boolean, Double, Float, Integer, String].;" + + "Value type of [Map] is not one of [Boolean, Double, Float, Integer, String].;" ) ); } diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/openai/OpenAiTaskSettingsTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/openai/OpenAiTaskSettingsTests.java index 5de993462b202..153a0c6196309 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/openai/OpenAiTaskSettingsTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/openai/OpenAiTaskSettingsTests.java @@ -196,7 +196,7 @@ public void testFromMap_ParsesCorrectly_WhenHeadersContainsAnInteger() { exception.getMessage(), is( "Validation Failed: 1: Map field [headers] has an entry that is not valid, " - + "[key => 1]. Value type of [1] is not one of [String].;" + + "[key => 1]. Value type of [Integer] is not one of [String].;" ) ); } From e8d3d8a87cee27c365beff3c201245e6e9a9320e Mon Sep 17 00:00:00 2001 From: Edoardo Tenani <526307+endorama@users.noreply.github.com> Date: Tue, 3 Mar 2026 17:34:28 +0100 Subject: [PATCH 072/137] apm-data: explicit map of timestamp.us to long (#143173) * add test to verify timestamp.us mapping and timestamp.us coercion behavior * explicitly map timestamp.us to long * apm-data: bump resource version --- docs/changelog/143173.yaml | 5 ++++ .../component-templates/apm@mappings.yaml | 4 +++ .../src/main/resources/resources.yaml | 2 +- .../resources/rest-api-spec/test/10_apm.yml | 30 +++++++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 docs/changelog/143173.yaml diff --git a/docs/changelog/143173.yaml b/docs/changelog/143173.yaml new file mode 100644 index 0000000000000..9c9b61f7546a3 --- /dev/null +++ b/docs/changelog/143173.yaml @@ -0,0 +1,5 @@ +area: Data streams +issues: [] +pr: 143173 +summary: "Apm-data: explicit map of `timestamp.us` to long" +type: bug diff --git a/x-pack/plugin/apm-data/src/main/resources/component-templates/apm@mappings.yaml b/x-pack/plugin/apm-data/src/main/resources/component-templates/apm@mappings.yaml index a5a3a7433f4c1..ebb6cb35c5769 100644 --- a/x-pack/plugin/apm-data/src/main/resources/component-templates/apm@mappings.yaml +++ b/x-pack/plugin/apm-data/src/main/resources/component-templates/apm@mappings.yaml @@ -17,3 +17,7 @@ template: type: constant_keyword data_stream.namespace: type: constant_keyword + timestamp: + properties: + us: + type: long diff --git a/x-pack/plugin/apm-data/src/main/resources/resources.yaml b/x-pack/plugin/apm-data/src/main/resources/resources.yaml index 9704557063bc5..37c4ce529399b 100644 --- a/x-pack/plugin/apm-data/src/main/resources/resources.yaml +++ b/x-pack/plugin/apm-data/src/main/resources/resources.yaml @@ -1,7 +1,7 @@ # "version" holds the version of the templates and ingest pipelines installed # by xpack-plugin apm-data. This must be increased whenever an existing template or # pipeline is changed, in order for it to be updated on Elasticsearch upgrade. -version: 102 +version: 103 component-templates: # Data lifecycle. diff --git a/x-pack/plugin/apm-data/src/yamlRestTest/resources/rest-api-spec/test/10_apm.yml b/x-pack/plugin/apm-data/src/yamlRestTest/resources/rest-api-spec/test/10_apm.yml index 64e7c12caeef3..3fe35e23ef6fe 100644 --- a/x-pack/plugin/apm-data/src/yamlRestTest/resources/rest-api-spec/test/10_apm.yml +++ b/x-pack/plugin/apm-data/src/yamlRestTest/resources/rest-api-spec/test/10_apm.yml @@ -17,6 +17,36 @@ setup: - contains: {index_templates: {name: traces-apm.rum@template}} - contains: {index_templates: {name: traces-apm.sampled@template}} +--- +# This is a regression test to avoid incurring in APM Server bug https://github.com/elastic/apm-server/issues/20496 +"Test apm timestamp.us mapping": + - do: + cluster.get_component_template: + name: apm@mappings + - match: + component_templates.0.component_template.template.mappings.properties.timestamp.properties.us.type: long + +--- +"Test apm timestamp.us coercion": + - do: + index: + index: traces-apm-timestampus + refresh: true + body: + "@timestamp": "2017-06-22T00:00:00Z" + data_stream.type: traces + data_stream.dataset: apm + data_stream.namespace: testing + timestamp: + us: 1772469840000000.0 + - do: + search: + index: traces-apm-timestampus + body: + fields: ["timestamp.us"] + - length: { hits.hits: 1 } + - match: { hits.hits.0.fields.timestamp\.us: [1772469840000000] } + --- "Test metrics-apm* template installation": - skip: From 7fcbee44a982d7de0adf0b38e55b10f2953614c9 Mon Sep 17 00:00:00 2001 From: Pawan Kartik Date: Tue, 3 Mar 2026 22:23:14 +0530 Subject: [PATCH 073/137] CPS fix: include only relevant projects in the search response metadata (#143367) --- .../action/search/TransportSearchAction.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java b/server/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java index 68ef689a20858..bb86705af16a2 100644 --- a/server/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java +++ b/server/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java @@ -1212,6 +1212,16 @@ private static void mergeResolvedIndices( } } + /* + * Projects that do not host the indices participating in a search should not appear in + * the search response's metadata. For MRT=false, this is handled by reconcileProjects(). + * For MRT=true, we handle it here. + */ + boolean includeOriginProjectInMetadata = rewritten.getResolvedIndexExpressions() + .expressions() + .stream() + .anyMatch(e -> e.localExpressions().localIndexResolutionResult() == ResolvedIndexExpression.LocalIndexResolutionResult.SUCCESS); + ElasticsearchException ex = CrossProjectIndexResolutionValidator.validate( rewritten.indicesOptions(), rewritten.getProjectRouting(), @@ -1246,7 +1256,7 @@ private static void mergeResolvedIndices( listener.onResponse( new ResolvedIndices( participatingLinkedProjects, - resolvedIndicesForCps.getLocalIndices(), + includeOriginProjectInMetadata ? originalResolvedIndices.getLocalIndices() : null, resolvedIndicesForCps.getConcreteLocalIndicesMetadata() ) ); From 16e0828d004c315bfd2e4158e983eb67a069b612 Mon Sep 17 00:00:00 2001 From: Chris Hegarty <62058229+ChrisHegarty@users.noreply.github.com> Date: Tue, 3 Mar 2026 17:45:42 +0000 Subject: [PATCH 074/137] Fix IndexInputUtils.withSlice to produce native-safe MemorySegments on Java 21 (#143479) On Java 21, FFI disallows passing heap-backed MemorySegments to native downcalls. Java 22+ removes this restriction. IndexInputUtils.withSlice is now the single path through which all simdvec scorers obtain MemorySegments from IndexInput data, and several of those scorers pass the segment directly to native downcalls. Rather than patching each and every call site across scorer classes individually, this fix takes a "safety by design" approach: withSlice itself now guarantees that the segment it hands to callers is always native-safe, regardless of Java version. No current or future caller needs to worry about the heap-segment restriction, correctness is enforced at the source. I also added an assertion to the DirectAccessInput path that the byte buffer is direct, documenting the invariant that real implementations always provide native-backed buffers. The tradeoff here is that on Java 21 only, the copyAndApply fallback path incurs an extra native allocation and copy (via a confined Arena) where a heap-backed segment would have sufficed, since a number of call sites only use the Panama Vector API and never touch native downcalls. On Java 22+ the behavior is unchanged. This is an acceptable cost: the fallback path is already the slowest path (mmap and direct buffer paths are preferred), and the alternative - requiring every call site to independently guard against heap segments, is fragile and has already proven easy to miss. We can do some further cleanup at the call site after this fix has been merged. caused by #141718 closes #143441 --- .../simdvec/internal/IndexInputUtils.java | 31 ++++++++++++++----- .../internal/IndexInputUtilsTests.java | 31 +++++++++++++++++-- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/libs/simdvec/src/main21/java/org/elasticsearch/simdvec/internal/IndexInputUtils.java b/libs/simdvec/src/main21/java/org/elasticsearch/simdvec/internal/IndexInputUtils.java index 41985352a1af0..b61450427fb34 100644 --- a/libs/simdvec/src/main21/java/org/elasticsearch/simdvec/internal/IndexInputUtils.java +++ b/libs/simdvec/src/main21/java/org/elasticsearch/simdvec/internal/IndexInputUtils.java @@ -15,7 +15,9 @@ import org.elasticsearch.core.DirectAccessInput; import java.io.IOException; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; import java.util.function.IntFunction; /** @@ -74,6 +76,7 @@ public static R withSlice( @SuppressWarnings("unchecked") R[] result = (R[]) new Object[1]; boolean available = dai.withByteBufferSlice(offset, length, bb -> { + assert bb.isDirect(); in.skipBytes(length); result[0] = action.apply(MemorySegment.ofBuffer(bb)); }); @@ -81,7 +84,7 @@ public static R withSlice( return result[0]; } } - return action.apply(copyOnHeap(in, Math.toIntExact(length), scratchSupplier)); + return copyAndApply(in, Math.toIntExact(length), scratchSupplier, action); } /** @@ -100,15 +103,29 @@ public static void checkInputType(IndexInput in) { } } + private static final boolean SUPPORTS_HEAP_SEGMENTS = Runtime.version().feature() >= 22; + /** - * Reads the given number of bytes from the current position of the - * given IndexInput into a heap-backed memory segment. The returned - * segment is sliced to exactly {@code bytesToRead} bytes, even if - * the underlying array is larger. + * Reads bytes from the index input and applies the action to a memory + * segment containing the data. On Java 22+ a heap-backed segment is + * used directly. On Java 21, where heap segments cannot be passed to + * native downcalls, the data is copied into a confined arena. */ - private static MemorySegment copyOnHeap(IndexInput in, int bytesToRead, IntFunction scratchSupplier) throws IOException { + private static R copyAndApply( + IndexInput in, + int bytesToRead, + IntFunction scratchSupplier, + CheckedFunction action + ) throws IOException { byte[] buf = scratchSupplier.apply(bytesToRead); in.readBytes(buf, 0, bytesToRead); - return MemorySegment.ofArray(buf).asSlice(0, bytesToRead); + if (SUPPORTS_HEAP_SEGMENTS) { + return action.apply(MemorySegment.ofArray(buf).asSlice(0, bytesToRead)); + } + try (Arena arena = Arena.ofConfined()) { + MemorySegment nativeSegment = arena.allocate(bytesToRead); + MemorySegment.copy(buf, 0, nativeSegment, ValueLayout.JAVA_BYTE, 0, bytesToRead); + return action.apply(nativeSegment); + } } } diff --git a/libs/simdvec/src/test21/java/org/elasticsearch/simdvec/internal/IndexInputUtilsTests.java b/libs/simdvec/src/test21/java/org/elasticsearch/simdvec/internal/IndexInputUtilsTests.java index 5edfaa16a7af7..683060fd3ad53 100644 --- a/libs/simdvec/src/test21/java/org/elasticsearch/simdvec/internal/IndexInputUtilsTests.java +++ b/libs/simdvec/src/test21/java/org/elasticsearch/simdvec/internal/IndexInputUtilsTests.java @@ -21,7 +21,9 @@ import org.elasticsearch.test.ESTestCase; import java.io.IOException; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; import java.nio.ByteBuffer; import java.util.Arrays; @@ -72,6 +74,26 @@ public void testWithSlicePlainIndexInput() throws Exception { } } + public void testPlainInputFallbackProducesNativeSegmentOnJava21() throws Exception { + byte[] data = randomByteArrayOfLength(256); + try (Directory dir = new NIOFSDirectory(createTempDir())) { + writeData(dir, data); + try (IndexInput in = dir.openInput(FILE_NAME, IOContext.DEFAULT)) { + assertFalse(in instanceof MemorySegmentAccessInput); + assertFalse(in instanceof DirectAccessInput); + IndexInputUtils.withSlice(in, data.length, byte[]::new, segment -> { + if (Runtime.version().feature() < 22) { + assertTrue("segment should be native-backed on Java 21", segment.heapBase().isEmpty()); + } + byte[] buf = new byte[(int) segment.byteSize()]; + MemorySegment.ofArray(buf).copyFrom(segment); + assertArrayEquals(data, buf); + return null; + }); + } + } + } + // -- constructor validation tests ----------------------------------------- public void testES92ConstructorAcceptsPlainInput() throws Exception { @@ -167,9 +189,12 @@ static class DirectAccessWrapper extends FilterIndexInput implements DirectAcces @Override public boolean withByteBufferSlice(long offset, long length, CheckedConsumer action) throws IOException { - ByteBuffer bb = ByteBuffer.wrap(data, (int) offset, (int) length).asReadOnlyBuffer(); - action.accept(bb); - return true; + try (Arena arena = Arena.ofConfined()) { + MemorySegment segment = arena.allocate(length); + MemorySegment.copy(data, (int) offset, segment, ValueLayout.JAVA_BYTE, 0, (int) length); + action.accept(segment.asByteBuffer().asReadOnlyBuffer()); + return true; + } } @Override From b7b41c46607739601c218406ea255921dea9122c Mon Sep 17 00:00:00 2001 From: Simon Cooper Date: Tue, 3 Mar 2026 17:49:36 +0000 Subject: [PATCH 075/137] Fix KnnIndexTester to work with byte vectors (#143493) --- .../elasticsearch/test/knn/KnnIndexer.java | 2 +- .../elasticsearch/test/knn/KnnSearcher.java | 22 +++++++++---------- .../test/knn/TestConfiguration.java | 6 +++++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/qa/vector/src/main/java/org/elasticsearch/test/knn/KnnIndexer.java b/qa/vector/src/main/java/org/elasticsearch/test/knn/KnnIndexer.java index 98d629889feb8..43f9dbec22805 100644 --- a/qa/vector/src/main/java/org/elasticsearch/test/knn/KnnIndexer.java +++ b/qa/vector/src/main/java/org/elasticsearch/test/knn/KnnIndexer.java @@ -448,7 +448,7 @@ synchronized void next(float[] dest) throws IOException { synchronized void next(byte[] dest) throws IOException { readNext(); - bytes.get(dest); + bytes.get(dest).position(0); } } } diff --git a/qa/vector/src/main/java/org/elasticsearch/test/knn/KnnSearcher.java b/qa/vector/src/main/java/org/elasticsearch/test/knn/KnnSearcher.java index b89c80ab66d8b..d20d81bf2b7f3 100644 --- a/qa/vector/src/main/java/org/elasticsearch/test/knn/KnnSearcher.java +++ b/qa/vector/src/main/java/org/elasticsearch/test/knn/KnnSearcher.java @@ -393,12 +393,10 @@ private int[][] getOrCalculateExactNN(int vectorFileOffsetBytes, SearchParameter long startNS = System.nanoTime(); // TODO: enable computing NN from high precision vectors when // checking low-precision recall - int[][] nn; - if (vectorEncoding.equals(VectorEncoding.BYTE)) { - nn = computeExactNNByte(queryPath, filterQuery, vectorFileOffsetBytes); - } else { - nn = computeExactNN(queryPath, filterQuery, searchParameters.topK(), vectorFileOffsetBytes); - } + int[][] nn = switch (vectorEncoding) { + case BYTE -> computeExactNNByte(queryPath, filterQuery, searchParameters.topK(), vectorFileOffsetBytes); + case FLOAT32 -> computeExactNN(queryPath, filterQuery, searchParameters.topK(), vectorFileOffsetBytes); + }; writeExactNN(nn, nnPath); long elapsedMS = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNS); // ns -> ms logger.info("computed " + numQueryVectors + " exact matches in " + elapsedMS + " ms"); @@ -562,7 +560,7 @@ private int[][] computeExactNN(Path queryPath, Query filterQuery, int topK, int } } - private int[][] computeExactNNByte(Path queryPath, Query filterQuery, int vectorFileOffsetBytes) throws IOException { + private int[][] computeExactNNByte(Path queryPath, Query filterQuery, int topK, int vectorFileOffsetBytes) throws IOException { int[][] result = new int[numQueryVectors][]; try (Directory dir = FSDirectory.open(indexPath); DirectoryReader reader = DirectoryReader.open(dir)) { List> tasks = new ArrayList<>(); @@ -571,7 +569,7 @@ private int[][] computeExactNNByte(Path queryPath, Query filterQuery, int vector for (int i = 0; i < numQueryVectors; i++) { byte[] queryVector = new byte[dim]; queryReader.next(queryVector); - tasks.add(new ComputeNNByteTask(i, queryVector, result, reader, filterQuery, similarityFunction)); + tasks.add(new ComputeNNByteTask(i, topK, queryVector, result, reader, filterQuery, similarityFunction)); } ForkJoinPool.commonPool().invokeAll(tasks); } @@ -637,11 +635,13 @@ static class ComputeNNByteTask implements Callable { private final byte[] query; private final int[][] result; private final IndexReader reader; - private final Query filterQuery; private final VectorSimilarityFunction similarityFunction; + private final Query filterQuery; + private final int topK; ComputeNNByteTask( int queryOrd, + int topK, byte[] query, int[][] result, IndexReader reader, @@ -652,14 +652,14 @@ static class ComputeNNByteTask implements Callable { this.query = query; this.result = result; this.reader = reader; - this.filterQuery = filterQuery; this.similarityFunction = similarityFunction; + this.filterQuery = filterQuery; + this.topK = topK; } @Override public Void call() { IndexSearcher searcher = new IndexSearcher(reader); - int topK = result[0].length; try { var queryVector = new ConstKnnByteVectorValueSource(query); var docVectors = new ByteKnnVectorFieldSource(VECTOR_FIELD); diff --git a/qa/vector/src/main/java/org/elasticsearch/test/knn/TestConfiguration.java b/qa/vector/src/main/java/org/elasticsearch/test/knn/TestConfiguration.java index 7f41bb42b7316..4fd97b379655a 100644 --- a/qa/vector/src/main/java/org/elasticsearch/test/knn/TestConfiguration.java +++ b/qa/vector/src/main/java/org/elasticsearch/test/knn/TestConfiguration.java @@ -526,6 +526,7 @@ public Builder setDirectoryType(String directoryType) { ".fvec" ], "queries": ".fvec", + "vector_encoding": "float32", // optional, default float32 "dimensions": 512, "vector_space": "cosine", "num_doc_vectors": 10000000, @@ -568,6 +569,7 @@ private void resolveDataset() throws Exception { ).getFirst(); } + Object vectorEncoding = dsData.get("vector_encoding"); String vectorSpace = dsData.get("vector_space").toString(); int numDocVectors = ((Number) dsData.get("num_doc_vectors")).intValue(); int numQueryVectors = ((Number) dsData.get("num_query_vectors")).intValue(); @@ -583,6 +585,10 @@ private void resolveDataset() throws Exception { docVectors = data; queryVectors = queries; + // vector encoding is optional (default float32) + if (vectorEncoding != null) { + setVectorEncoding(vectorEncoding.toString()); + } setDimensions(-1); // dataset dimensions is documentation, the tester reads the dimensions from the fvec files // vector space might already be set explicitly from the config file if (this.vectorSpace == null) { From 48528dfa9588c387f296404e67163c0d8439e31f Mon Sep 17 00:00:00 2001 From: Fabrizio Ferri-Benedetti Date: Tue, 3 Mar 2026 18:50:49 +0100 Subject: [PATCH 076/137] Update docs-build.yml (#142958) --- .github/workflows/docs-build.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index f3fa24d921947..b418cfea0f154 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -11,6 +11,11 @@ jobs: docs-preview: uses: elastic/docs-builder/.github/workflows/preview-build.yml@main with: + enable-vale-linting: true + include-paths: | + docs/reference/** + docs/extend/** + !docs/reference/query-languages/esql/** path-pattern: docs/** path-pattern-ignore: docs/changelog/**/*.yaml enable-cumulative-comment: true From e1bb1574c843e4aeb3c88f1611aa695442f050e7 Mon Sep 17 00:00:00 2001 From: Luigi Dell'Aquila Date: Tue, 3 Mar 2026 18:57:33 +0100 Subject: [PATCH 077/137] ES|QL: Fix LIMIT after all columns are dropped (#143463) --- docs/changelog/143463.yaml | 6 +++ .../compute/operator/LimitOperator.java | 2 +- .../compute/operator/LimitOperatorTests.java | 18 +++++++ .../xpack/esql/action/EsqlCapabilities.java | 6 +++ .../rest-api-spec/test/esql/100_bug_fix.yml | 49 +++++++++++++++++++ 5 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 docs/changelog/143463.yaml diff --git a/docs/changelog/143463.yaml b/docs/changelog/143463.yaml new file mode 100644 index 0000000000000..88d57f6aeb3f3 --- /dev/null +++ b/docs/changelog/143463.yaml @@ -0,0 +1,6 @@ +area: ES|QL +issues: + - 142473 +pr: 143463 +summary: Fix LIMIT after all columns are dropped +type: bug diff --git a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/LimitOperator.java b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/LimitOperator.java index 9e2073d5f04b5..d44d59035c2a3 100644 --- a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/LimitOperator.java +++ b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/LimitOperator.java @@ -123,7 +123,7 @@ private static Page truncatePage(Page page, int upTo) { for (int b = 0; b < blocks.length; b++) { blocks[b] = page.getBlock(b).filter(false, filter); } - result = new Page(blocks); + result = new Page(upTo, blocks); } finally { if (result == null) { Releasables.closeExpectNoException(page::releaseBlocks, Releasables.wrap(blocks)); diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/LimitOperatorTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/LimitOperatorTests.java index 88278cc46bda7..b06c4fb67d539 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/LimitOperatorTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/LimitOperatorTests.java @@ -136,6 +136,24 @@ public void testBlockPreciselyRemaining() { } } + public void testTruncatePageWithZeroBlocks() { + try (var op = simple().get(driverContext())) { + assertTrue(op.needsInput()); + Page p = new Page(200); + op.addInput(p); + assertFalse(op.needsInput()); + Page result = op.getOutput(); + try { + assertThat(result.getPositionCount(), equalTo(100)); + assertThat(result.getBlockCount(), equalTo(0)); + } finally { + result.releaseBlocks(); + } + assertFalse(op.needsInput()); + assertTrue(op.isFinished()); + } + } + public void testEarlyTermination() { int numDrivers = between(1, 4); final List drivers = new ArrayList<>(); 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 49981e5ee468d..6a8ef525ad6c9 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 @@ -1700,6 +1700,12 @@ public enum Cap { */ FIX_NO_COLUMNS, + /** + * Fix LimitOperator truncation with zero columns + * https://github.com/elastic/elasticsearch/issues/142473 + */ + FIX_LIMIT_TRUNCATION_WITH_ZERO_COLUMNS, + /** * Support for dots in FUSE attributes */ diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/100_bug_fix.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/100_bug_fix.yml index 208649ac40bed..3f4db4c395861 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/100_bug_fix.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/100_bug_fix.yml @@ -390,3 +390,52 @@ - match: { values.0.1: null } - match: { values.1.0: null } - match: { values.1.1: null } + +--- +"Limit truncation with zero columns #142473": + - requires: + test_runner_features: [capabilities] + capabilities: + - method: POST + path: /_query + parameters: [] + capabilities: [fix_limit_truncation_with_zero_columns] + reason: "fixed LimitOperator truncation with zero columns" + - do: + indices.create: + index: test_limit_zero_cols + body: + mappings: + properties: + value: + type: integer + - do: + bulk: + refresh: true + body: + - { "index": { "_index": "test_limit_zero_cols" } } + - { "value": 1 } + - { "index": { "_index": "test_limit_zero_cols" } } + - { "value": 2 } + - { "index": { "_index": "test_limit_zero_cols" } } + - { "value": 3 } + - { "index": { "_index": "test_limit_zero_cols" } } + - { "value": 4 } + - { "index": { "_index": "test_limit_zero_cols" } } + - { "value": 5 } + - { "index": { "_index": "test_limit_zero_cols" } } + - { "value": 6 } + - { "index": { "_index": "test_limit_zero_cols" } } + - { "value": 7 } + - { "index": { "_index": "test_limit_zero_cols" } } + - { "value": 8 } + - { "index": { "_index": "test_limit_zero_cols" } } + - { "value": 9 } + - { "index": { "_index": "test_limit_zero_cols" } } + - { "value": 10 } + - do: + esql.query: + body: + query: 'FROM test_limit_zero_cols | EVAL x = "test" | KEEP x | DROP x | LIMIT 5' + - length: { columns: 0 } + - length: { values: 5 } From 0716220d72cba3e8208415ce45fffb5cbe5af22e Mon Sep 17 00:00:00 2001 From: Alireza Heidarikhazaei Date: Tue, 3 Mar 2026 10:00:32 -0800 Subject: [PATCH 078/137] Documentation for query_vector base64 parameter (#142675) * Documentation for query_vector parameter Update documentation for query_vector parameter in diversify and knn retrievers to include base64-encoded vector string support and clarify hex-encoded byte vector usage. Relates to #138190 * Added tag * Update docs/reference/elasticsearch/rest-apis/retrievers/diversify-retriever.md Co-authored-by: Benjamin Trent * Update documentation for query_vector parameter Adding big-endianess * Update docs/reference/query-languages/query-dsl/query-dsl-knn-query.md Co-authored-by: Liam Thompson * Update docs/reference/elasticsearch/rest-apis/retrievers/diversify-retriever.md Co-authored-by: Liam Thompson * Update docs/reference/query-languages/query-dsl/query-dsl-knn-query.md Co-authored-by: Liam Thompson * Update docs/reference/query-languages/query-dsl/query-dsl-knn-query.md Co-authored-by: Liam Thompson * Update docs/reference/query-languages/query-dsl/query-dsl-knn-query.md Co-authored-by: Liam Thompson * Removes redundant code block from documentation Eliminates an unnecessary code block for improved clarity and readability in the documentation. No content functionality is affected. --------- Co-authored-by: Benjamin Trent Co-authored-by: Liam Thompson --- .../retrievers/diversify-retriever.md | 7 +++- .../rest-apis/retrievers/knn-retriever.md | 8 +++- .../query-dsl/query-dsl-knn-query.md | 41 ++++++++++++++++++- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/docs/reference/elasticsearch/rest-apis/retrievers/diversify-retriever.md b/docs/reference/elasticsearch/rest-apis/retrievers/diversify-retriever.md index 969dc02612c0b..76d54528e0d2b 100644 --- a/docs/reference/elasticsearch/rest-apis/retrievers/diversify-retriever.md +++ b/docs/reference/elasticsearch/rest-apis/retrievers/diversify-retriever.md @@ -46,10 +46,13 @@ The ordering of results returned from the inner retriever is preserved. ::: `query_vector` -: (Optional, array of `float` or `byte`) +: (Optional, array of `float` or `byte`, or string) Query vector. Must have the same number of dimensions as the vector field you are searching against. - Must be either an array of floats or a hex-encoded byte vector. + Must be one of: + - An array of floats + - A hex-encoded byte vector (one byte per dimension; for `bit`, one byte per 8 dimensions){applies_to}`stack: ga 9.0-9.3` + - A base64-encoded vector string. Base64 supports `float` and `bfloat16` (big-endian), `byte`, and `bit` encodings depending on the target field type. {applies_to}`stack: ga 9.4` If you provide a `query_vector`, you cannot also provide a `query_vector_builder`. `query_vector_builder` diff --git a/docs/reference/elasticsearch/rest-apis/retrievers/knn-retriever.md b/docs/reference/elasticsearch/rest-apis/retrievers/knn-retriever.md index b64ea8216e7a5..75120175b9cdf 100644 --- a/docs/reference/elasticsearch/rest-apis/retrievers/knn-retriever.md +++ b/docs/reference/elasticsearch/rest-apis/retrievers/knn-retriever.md @@ -18,9 +18,13 @@ A kNN retriever returns top documents from a [k-nearest neighbor search (kNN)](d `query_vector` -: (Required if `query_vector_builder` is not defined, array of `float`) +: (Required if `query_vector_builder` is not defined, array of `float` or string) - Query vector. Must have the same number of dimensions as the vector field you are searching against. Must be either an array of floats or a hex-encoded byte vector. + Query vector. Must have the same number of dimensions as the vector field you are searching against. + Must be one of: + - An array of floats + - A hex-encoded byte vector (one byte per dimension; for `bit`, one byte per 8 dimensions). {applies_to}`stack: ga 9.0-9.3` + - A base64-encoded vector string. Base64 supports `float` and `bfloat16` (big-endian), `byte`, and `bit` encodings depending on the target field type. {applies_to}`stack: ga 9.4` {applies_to}`serverless: ga` `query_vector_builder` diff --git a/docs/reference/query-languages/query-dsl/query-dsl-knn-query.md b/docs/reference/query-languages/query-dsl/query-dsl-knn-query.md index 778784c7058e3..a46572bcd04c7 100644 --- a/docs/reference/query-languages/query-dsl/query-dsl-knn-query.md +++ b/docs/reference/query-languages/query-dsl/query-dsl-knn-query.md @@ -66,6 +66,40 @@ PUT my-image-index ``` % TEST[continued] +3. {applies_to}`stack: ga 9.0-9.3` You can also provide a hex-encoded query vector string. Hex query vectors are byte-oriented (one byte per dimension, represented as two hex characters). For example, `[-5, 9, -12]` as signed bytes is `fb09f4`. + + ```console + POST my-image-index/_search + { + "size" : 3, + "query" : { + "knn": { + "field": "image-vector", + "query_vector": "fb09f4", + "k": 10 + } + } + } + ``` + % TEST[continued] + +4. {applies_to}`stack: ga 9.4` You can also provide a base64-encoded query vector string. For example, `[-5, 9, -12]` encoded as float32 big-endian bytes is `wKAAAEEQAADBQAAA`. + + ```console + POST my-image-index/_search + { + "size" : 3, + "query" : { + "knn": { + "field": "image-vector", + "query_vector": "wKAAAEEQAADBQAAA", + "k": 10 + } + } + } + ``` + % TEST[continued] + ## Top-level parameters for `knn` [knn-query-top-level-parameters] @@ -74,7 +108,12 @@ PUT my-image-index `query_vector` -: (Optional, array of floats or string) Query vector. Must have the same number of dimensions as the vector field you are searching against. Must be either an array of floats or a hex-encoded byte vector. Either this or `query_vector_builder` must be provided. +: (Optional, array of floats or string) Query vector. Must have the same number of dimensions as the vector field you are searching against. + Must be one of: + - An array of floats + - A hex-encoded byte vector (one byte per dimension; for `bit`, one byte per 8 dimensions). {applies_to}`stack: ga 9.0-9.3` + - A base64-encoded vector string. Base64 supports `float` and `bfloat16` (big-endian), `byte`, and `bit` encodings depending on the target field type. {applies_to}`stack: ga 9.4` {applies_to}`serverless: ga` + Either this or `query_vector_builder` must be provided. `query_vector_builder` From 420e929a510cc451c6972a09253263923efb54c4 Mon Sep 17 00:00:00 2001 From: Szymon Bialkowski Date: Tue, 3 Mar 2026 18:13:42 +0000 Subject: [PATCH 079/137] Stop and relocate sliced reindex on shutdown (#143183) --- .../management/ReindexRelocationIT.java | 289 +++++++++++------- .../AbstractAsyncBulkByScrollAction.java | 9 +- .../org/elasticsearch/reindex/Reindexer.java | 55 +++- .../elasticsearch/reindex/ReindexerTests.java | 30 +- .../reindex/LeaderBulkByScrollTaskState.java | 71 +++++ .../index/reindex/ReindexRequest.java | 1 + .../reindex/WorkerBulkByScrollTaskState.java | 6 +- .../LeaderBulkByScrollTaskStateTests.java | 185 +++++++++++ 8 files changed, 516 insertions(+), 130 deletions(-) diff --git a/modules/reindex-management/src/internalClusterTest/java/org/elasticsearch/reindex/management/ReindexRelocationIT.java b/modules/reindex-management/src/internalClusterTest/java/org/elasticsearch/reindex/management/ReindexRelocationIT.java index 80417d6b14507..37c4e99c2a427 100644 --- a/modules/reindex-management/src/internalClusterTest/java/org/elasticsearch/reindex/management/ReindexRelocationIT.java +++ b/modules/reindex-management/src/internalClusterTest/java/org/elasticsearch/reindex/management/ReindexRelocationIT.java @@ -17,6 +17,7 @@ import org.elasticsearch.client.RestClient; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodeRole; +import org.elasticsearch.common.CheckedBiFunction; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.core.Strings; import org.elasticsearch.core.TimeValue; @@ -25,6 +26,8 @@ import org.elasticsearch.index.reindex.ReindexAction; import org.elasticsearch.node.ShutdownPrepareService; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.plugins.PluginsService; +import org.elasticsearch.reindex.ReindexMetrics; import org.elasticsearch.reindex.ReindexPlugin; import org.elasticsearch.reindex.TransportReindexAction; import org.elasticsearch.rest.root.MainRestPlugin; @@ -33,6 +36,8 @@ import org.elasticsearch.tasks.TaskInfo; import org.elasticsearch.tasks.TaskResult; import org.elasticsearch.tasks.TaskResultsService; +import org.elasticsearch.telemetry.Measurement; +import org.elasticsearch.telemetry.TestTelemetryPlugin; import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.NodeRoles; import org.elasticsearch.test.rest.ESRestTestCase; @@ -46,6 +51,7 @@ import java.net.InetSocketAddress; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; @@ -54,6 +60,8 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures; import static org.hamcrest.Matchers.aMapWithSize; import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.closeTo; +import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThanOrEqualTo; @@ -64,21 +72,29 @@ import static org.hamcrest.Matchers.startsWith; /** - * Integration test(s) for reindex task relocation on node shutdown. + * Integration test(s) for testing a long-running reindex task is relocated to a suitable node on shutdown. + * Checks expected state at each task phase: initial running, initial relocated, relocated running, and relocated finished. + *

+ * Each test follows this flow: + * 1. Create two data nodes: nodeA (hosting source and destination indices) and nodeB (hosting the reindex task) + * 2. Create the source index pinned to nodeA without replicas, so the scroll always lives there + * 3. Create the destination index pinned to nodeA without replicas, so it's available when we shutdown nodeB + * 4. Start a throttled reindex on nodeB (depending on test: local sliced or unsliced, or non-sliced remote) + * 5. Stop nodeB and observe relocation to nodeA */ @ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST, numDataNodes = 0, numClientNodes = 0) public class ReindexRelocationIT extends ESIntegTestCase { private static final String SOURCE_INDEX = "reindex_src"; private static final String DEST_INDEX = "reindex_dst"; - private static final int BULK_SIZE = 1; - private static final int REQUESTS_PER_SECOND = 1; - private static final int NUM_OF_SLICES = 1; - private static final int NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST = 60 * REQUESTS_PER_SECOND * BULK_SIZE; + + private final int bulkSize = randomIntBetween(1, 5); + private final int requestsPerSecond = randomIntBetween(1, 5); + private final int numberOfDocumentsThatTakes60SecondsToIngest = 60 * requestsPerSecond * bulkSize; @Override protected Collection> nodePlugins() { - return Arrays.asList(ReindexPlugin.class, ReindexManagementPlugin.class, MainRestPlugin.class); + return Arrays.asList(ReindexPlugin.class, ReindexManagementPlugin.class, MainRestPlugin.class, TestTelemetryPlugin.class); } @Override @@ -94,65 +110,34 @@ protected Settings nodeSettings(int nodeOrdinal, Settings otherSettings) { .build(); } - /** - * Test long-running non-sliced reindex task is relocated to a suitable node by doing the following: - * 1. Create two data nodes: nodeA (hosting source and destination indices) and nodeB (hosting the reindex task) - * 2. Create the source index pinned to nodeA without replicas, so the scroll always lives there - * 3. Create the destination index pinned to nodeA without replicas, so it's available when we shutdown nodeB - * 4. Start a throttled reindex on nodeB - * 5. Stop nodeB and observe relocation to nodeA - */ - public void testNonSlicedReindexRelocation() throws Exception { - assumeTrue("reindex resilience is enabled", ReindexPlugin.REINDEX_RESILIENCE_ENABLED); - - final String nodeAName = internalCluster().startNode( - NodeRoles.onlyRoles(Set.of(DiscoveryNodeRole.DATA_ROLE, DiscoveryNodeRole.MASTER_ROLE)) - ); - final String nodeAId = nodeIdByName(nodeAName); - final String nodeBName = internalCluster().startNode( - NodeRoles.onlyRoles(Set.of(DiscoveryNodeRole.DATA_ROLE, DiscoveryNodeRole.MASTER_ROLE)) + public void testLocalReindexRelocation() throws Exception { + final int slices = randomIntBetween(1, 10); + testReindexRelocation( + (nodeAName, nodeBName) -> startAsyncThrottledLocalReindexOnNode(nodeBName, slices), + localReindexDescription(), + slices, + false ); - final String nodeBId = nodeIdByName(nodeBName); - ensureStableCluster(2); - - createIndexPinnedToNodeName(SOURCE_INDEX, nodeAName); - createIndexPinnedToNodeName(DEST_INDEX, nodeAName); - indexRandom(true, SOURCE_INDEX, NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST); - ensureGreen(SOURCE_INDEX, DEST_INDEX); - - final Matcher expectedTaskDescription = localReindexDescription(); - - // Start throttled async reindex on nodeB and check it has the expected state - final TaskId originalTaskId = startAsyncThrottledReindexOnNode(nodeBName); - final TaskResult originalReindex = getRunningReindex(originalTaskId); - assertThat("reindex should start on nodeB", originalReindex.getTask().taskId().getNodeId(), equalTo(nodeBId)); - assertRunningReindexTaskExpectedState(originalReindex.getTask(), expectedTaskDescription); - - shutdownNodeNameAndRelocate(nodeBName); - - // Assert the original task is in .tasks index and has expected content (including relocated taskId on nodeA) - final TaskId relocatedTaskId = assertOriginalTaskEndStateInTasksIndexAndGetRelocatedTaskId( - originalTaskId, - nodeAId, - expectedTaskDescription - ); - - // Assert relocated reindex is running and has expected state - final TaskResult relocatedReindex = getRunningReindex(relocatedTaskId); - assertThat("relocated reindex should be on nodeA", relocatedReindex.getTask().taskId().getNodeId(), equalTo(nodeAId)); - assertRunningReindexTaskExpectedState(relocatedReindex.getTask(), expectedTaskDescription); - - // Speed up reindex post-relocation to keep the test fast - unthrottleReindex(relocatedTaskId); - - assertRelocatedTaskExpectedEndState(relocatedTaskId, expectedTaskDescription); - - // assert all documents have been reindexed - assertDocCount(DEST_INDEX, NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST); } - /** Same test as above, but for remote reindex. */ public void testNonSlicedRemoteReindexRelocation() throws Exception { + final int slices = 1; + testReindexRelocation((nodeAName, nodeBName) -> { + final InetSocketAddress nodeAAddress = internalCluster().getInstance(HttpServerTransport.class, nodeAName) + .boundAddress() + .publishAddress() + .address(); + return startAsyncNonSlicedThrottledRemoteReindexOnNode(nodeBName, nodeAAddress); + }, remoteReindexDescription(), slices, true); + } + // no test for remote sliced reindex since it's not allowed + + private void testReindexRelocation( + final CheckedBiFunction startReindexGivenNodeAAndB, + final Matcher expectedDescription, + final int slices, + final boolean isRemote + ) throws Exception { assumeTrue("reindex resilience is enabled", ReindexPlugin.REINDEX_RESILIENCE_ENABLED); final String nodeAName = internalCluster().startNode( @@ -167,20 +152,14 @@ public void testNonSlicedRemoteReindexRelocation() throws Exception { createIndexPinnedToNodeName(SOURCE_INDEX, nodeAName); createIndexPinnedToNodeName(DEST_INDEX, nodeAName); - indexRandom(true, SOURCE_INDEX, NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST); + indexRandom(true, SOURCE_INDEX, numberOfDocumentsThatTakes60SecondsToIngest); ensureGreen(SOURCE_INDEX, DEST_INDEX); - final InetSocketAddress nodeAAddress = internalCluster().getInstance(HttpServerTransport.class, nodeAName) - .boundAddress() - .publishAddress() - .address(); - final Matcher expectedTaskDescription = remoteReindexDescription(nodeAAddress); - - // Start throttled async remote reindex on nodeB and check it has the expected state - final TaskId originalTaskId = startAsyncThrottledRemoteReindexOnNode(nodeBName, nodeAAddress); + // Start throttled async reindex on nodeB and check it has the expected state + final TaskId originalTaskId = startReindexGivenNodeAAndB.apply(nodeAName, nodeBName); final TaskResult originalReindex = getRunningReindex(originalTaskId); assertThat("reindex should start on nodeB", originalReindex.getTask().taskId().getNodeId(), equalTo(nodeBId)); - assertRunningReindexTaskExpectedState(originalReindex.getTask(), expectedTaskDescription); + assertRunningReindexTaskExpectedState(originalReindex.getTask(), expectedDescription, slices); shutdownNodeNameAndRelocate(nodeBName); @@ -188,21 +167,25 @@ public void testNonSlicedRemoteReindexRelocation() throws Exception { final TaskId relocatedTaskId = assertOriginalTaskEndStateInTasksIndexAndGetRelocatedTaskId( originalTaskId, nodeAId, - expectedTaskDescription + expectedDescription, + slices ); // Assert relocated reindex is running and has expected state final TaskResult relocatedReindex = getRunningReindex(relocatedTaskId); assertThat("relocated reindex should be on nodeA", relocatedReindex.getTask().taskId().getNodeId(), equalTo(nodeAId)); - assertRunningReindexTaskExpectedState(relocatedReindex.getTask(), expectedTaskDescription); + assertRunningReindexTaskExpectedState(relocatedReindex.getTask(), expectedDescription, slices); // Speed up reindex post-relocation to keep the test fast unthrottleReindex(relocatedTaskId); - assertRelocatedTaskExpectedEndState(relocatedTaskId, expectedTaskDescription); + assertRelocatedTaskExpectedEndState(relocatedTaskId, expectedDescription, slices); + + // Assert nodeA recorded success metrics for the relocated reindex + assertReindexSuccessMetricsOnNode(nodeAName, isRemote, slices); // assert all documents have been reindexed - assertDocCount(DEST_INDEX, NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST); + assertExpectedNumberOfDocumentsInDestinationIndex(); } private void shutdownNodeNameAndRelocate(final String nodeName) throws Exception { @@ -212,6 +195,8 @@ private void shutdownNodeNameAndRelocate(final String nodeName) throws Exception // trigger reindex relocation internalCluster().getInstance(ShutdownPrepareService.class, nodeName).prepareForShutdown(); + assertNoReindexMetricsOnNode(nodeName); + // Wait for .tasks and replica to be created before stopping nodeB, otherwise the replica // on nodeA is stale and can't be promoted to primary when nodeB leaves assertBusy(() -> assertTrue(indexExists(TaskResultsService.TASK_INDEX)), 30, TimeUnit.SECONDS); @@ -224,7 +209,8 @@ private TaskId assertOriginalTaskExpectedEndStateAndGetRelocatedTaskId( final TaskResult originalResult, final TaskId originalTaskId, final String relocatedNodeId, - final Matcher expectedTaskDescription + final Matcher expectedTaskDescription, + final int slices ) { assertThat("task completed", originalResult.isCompleted(), is(true)); @@ -239,20 +225,37 @@ private TaskId assertOriginalTaskExpectedEndStateAndGetRelocatedTaskId( final Map taskStatus = ((RawTaskStatus) taskInfo.status()).toMap(); assertThat(taskStatus.get("slice_id"), is(nullValue())); - assertThat((Integer) taskStatus.get("total"), lessThanOrEqualTo(NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST)); + assertThat((Integer) taskStatus.get("total"), lessThanOrEqualTo(numberOfDocumentsThatTakes60SecondsToIngest)); assertThat(taskStatus.get("updated"), is(0)); - assertThat((Integer) taskStatus.get("created"), lessThan(NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST)); + assertThat((Integer) taskStatus.get("created"), lessThan(numberOfDocumentsThatTakes60SecondsToIngest)); assertThat(taskStatus.get("deleted"), is(0)); - assertThat((Integer) taskStatus.get("batches"), lessThan(NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST)); + assertThat( + (Integer) taskStatus.get("batches"), + lessThan((int) Math.floor((float) numberOfDocumentsThatTakes60SecondsToIngest / bulkSize)) + ); assertThat(taskStatus.get("version_conflicts"), is(0)); assertThat(taskStatus.get("noops"), is(0)); assertThat(ObjectPath.eval("retries.bulk", taskStatus), is(0)); assertThat(ObjectPath.eval("retries.search", taskStatus), is(0)); assertThat((Integer) taskStatus.get("throttled_millis"), greaterThanOrEqualTo(0)); - assertThat(taskStatus.get("requests_per_second"), is(1.0)); + assertThat((double) taskStatus.get("requests_per_second"), closeTo(requestsPerSecond, 0.00001)); + assertThat(taskStatus.get("reason_cancelled"), is(nullValue())); assertThat((Integer) taskStatus.get("throttled_until_millis"), greaterThanOrEqualTo(0)); + if (slices >= 2) { + @SuppressWarnings("unchecked") + final List> sliceStatuses = (List>) taskStatus.get("slices"); + assertThat(sliceStatuses.size(), equalTo(slices)); + for (int i = 0; i < slices; i++) { + final Map slice = sliceStatuses.get(i); + assertThat(slice.get("slice_id"), is(i)); + assertThat((double) slice.get("requests_per_second"), closeTo((double) requestsPerSecond / slices, 0.00001)); + } + } else { + assertThat(taskStatus.containsKey("slices"), is(false)); + } + final Map errorMap = originalResult.getErrorAsMap(); assertThat(errorMap, is(aMapWithSize(4))); assertThat("we get expected error type", errorMap.get("type"), equalTo("task_relocated_exception")); @@ -263,7 +266,8 @@ private TaskId assertOriginalTaskExpectedEndStateAndGetRelocatedTaskId( return new TaskId(relocatedTaskId); } - private void assertRelocatedTaskExpectedEndState(final TaskId taskId, final Matcher expectedTaskDescription) throws Exception { + private void assertRelocatedTaskExpectedEndState(final TaskId taskId, final Matcher expectedTaskDescription, final int slices) + throws Exception { final SetOnce finishedResult = new SetOnce<>(); assertBusy(() -> finishedResult.set(getCompletedTaskResult(taskId)), 30, TimeUnit.SECONDS); @@ -271,11 +275,14 @@ private void assertRelocatedTaskExpectedEndState(final TaskId taskId, final Matc assertThat("relocated task has no error", result.getError(), is(nullValue())); final Map innerResponse = result.getResponseAsMap(); assertThat(innerResponse.get("timed_out"), is(false)); - assertThat(innerResponse.get("total"), is(NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST)); + assertThat(innerResponse.get("total"), is(numberOfDocumentsThatTakes60SecondsToIngest)); assertThat(innerResponse.get("updated"), is(0)); - assertThat(innerResponse.get("created"), is(NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST)); + assertThat(innerResponse.get("created"), is(numberOfDocumentsThatTakes60SecondsToIngest)); assertThat(innerResponse.get("deleted"), is(0)); - assertThat(innerResponse.get("batches"), is(NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST)); + assertThat( + (int) innerResponse.get("batches"), + greaterThanOrEqualTo((int) Math.ceil((float) numberOfDocumentsThatTakes60SecondsToIngest / bulkSize)) + ); assertThat(innerResponse.get("version_conflicts"), is(0)); assertThat(innerResponse.get("noops"), is(0)); assertThat((Integer) innerResponse.get("throttled_millis"), greaterThanOrEqualTo(0)); @@ -291,11 +298,14 @@ private void assertRelocatedTaskExpectedEndState(final TaskId taskId, final Matc final Map taskStatus = ((RawTaskStatus) taskInfo.status()).toMap(); assertThat(taskStatus.get("slice_id"), is(nullValue())); - assertThat(taskStatus.get("total"), is(NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST)); + assertThat(taskStatus.get("total"), is(numberOfDocumentsThatTakes60SecondsToIngest)); assertThat(taskStatus.get("updated"), is(0)); - assertThat(taskStatus.get("created"), is(NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST)); + assertThat(taskStatus.get("created"), is(numberOfDocumentsThatTakes60SecondsToIngest)); assertThat(taskStatus.get("deleted"), is(0)); - assertThat(taskStatus.get("batches"), is(NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST)); + assertThat( + (int) taskStatus.get("batches"), + greaterThanOrEqualTo((int) Math.ceil((float) numberOfDocumentsThatTakes60SecondsToIngest / bulkSize)) + ); assertThat(taskStatus.get("version_conflicts"), is(0)); assertThat(taskStatus.get("noops"), is(0)); assertThat(ObjectPath.eval("retries.bulk", taskStatus), is(0)); @@ -304,12 +314,27 @@ private void assertRelocatedTaskExpectedEndState(final TaskId taskId, final Matc assertThat(taskStatus.get("requests_per_second"), is(-1.0)); assertThat(taskStatus.get("reason_cancelled"), is(nullValue())); assertThat((Integer) taskStatus.get("throttled_until_millis"), greaterThanOrEqualTo(0)); + + if (slices >= 2) { + @SuppressWarnings("unchecked") + final List> responseSlices = (List>) innerResponse.get("slices"); + assertThat(responseSlices.size(), equalTo(slices)); + int totalCreated = 0; + for (Map slice : responseSlices) { + assertThat(slice.get("requests_per_second"), is(-1.0)); + totalCreated += (Integer) slice.get("created"); + } + assertThat(totalCreated, equalTo(numberOfDocumentsThatTakes60SecondsToIngest)); + } else { + assertThat(innerResponse.containsKey("slices"), is(false)); + } } private TaskId assertOriginalTaskEndStateInTasksIndexAndGetRelocatedTaskId( final TaskId taskId, final String relocatedNodeId, - final Matcher expectedTaskDescription + final Matcher expectedTaskDescription, + final int slices ) { ensureYellowAndNoInitializingShards(TaskResultsService.TASK_INDEX); // replicas won't be allocated assertNoFailures(indicesAdmin().prepareRefresh(TaskResultsService.TASK_INDEX).get()); @@ -326,15 +351,15 @@ private TaskId assertOriginalTaskEndStateInTasksIndexAndGetRelocatedTaskId( throw new AssertionError("failed to parse task result from .tasks index", e); } - return assertOriginalTaskExpectedEndStateAndGetRelocatedTaskId(result, taskId, relocatedNodeId, expectedTaskDescription); + return assertOriginalTaskExpectedEndStateAndGetRelocatedTaskId(result, taskId, relocatedNodeId, expectedTaskDescription, slices); } - private TaskId startAsyncThrottledReindexOnNode(final String nodeName) throws Exception { + private TaskId startAsyncThrottledLocalReindexOnNode(final String nodeName, final int slices) throws Exception { try (RestClient restClient = createRestClient(nodeName)) { final Request request = new Request("POST", "/_reindex"); request.addParameter("wait_for_completion", "false"); - request.addParameter("slices", Integer.toString(NUM_OF_SLICES)); - request.addParameter("requests_per_second", Integer.toString(REQUESTS_PER_SECOND)); + request.addParameter("slices", Integer.toString(slices)); + request.addParameter("requests_per_second", Integer.toString(requestsPerSecond)); request.setJsonEntity(Strings.format(""" { "source": { @@ -345,7 +370,7 @@ private TaskId startAsyncThrottledReindexOnNode(final String nodeName) throws Ex "index": "%s" } } - """, SOURCE_INDEX, BULK_SIZE, DEST_INDEX)); + """, SOURCE_INDEX, bulkSize, DEST_INDEX)); final Response response = restClient.performRequest(request); final String task = (String) ESRestTestCase.entityAsMap(response).get("task"); @@ -354,12 +379,13 @@ private TaskId startAsyncThrottledReindexOnNode(final String nodeName) throws Ex } } - private TaskId startAsyncThrottledRemoteReindexOnNode(final String nodeName, final InetSocketAddress remoteAddress) throws Exception { + private TaskId startAsyncNonSlicedThrottledRemoteReindexOnNode(final String nodeName, final InetSocketAddress remoteAddress) + throws Exception { try (RestClient restClient = createRestClient(nodeName)) { final Request request = new Request("POST", "/_reindex"); request.addParameter("wait_for_completion", "false"); - request.addParameter("slices", Integer.toString(NUM_OF_SLICES)); - request.addParameter("requests_per_second", Integer.toString(REQUESTS_PER_SECOND)); + request.addParameter("slices", Integer.toString(1)); + request.addParameter("requests_per_second", Integer.toString(requestsPerSecond)); request.setJsonEntity(Strings.format(""" { "source": { @@ -373,7 +399,7 @@ private TaskId startAsyncThrottledRemoteReindexOnNode(final String nodeName, fin "index": "%s" } } - """, remoteAddress.getHostString(), remoteAddress.getPort(), SOURCE_INDEX, BULK_SIZE, DEST_INDEX)); + """, remoteAddress.getHostString(), remoteAddress.getPort(), SOURCE_INDEX, bulkSize, DEST_INDEX)); final Response response = restClient.performRequest(request); final String task = (String) ESRestTestCase.entityAsMap(response).get("task"); @@ -386,11 +412,8 @@ private static Matcher localReindexDescription() { return equalTo(Strings.format("reindex from [%s] to [%s]", SOURCE_INDEX, DEST_INDEX)); } - private static Matcher remoteReindexDescription(final InetSocketAddress remoteAddress) { - return allOf( - startsWith(Strings.format("reindex from [host=%s port=%d", remoteAddress.getHostString(), remoteAddress.getPort())), - endsWith(Strings.format("[%s] to [%s]", SOURCE_INDEX, DEST_INDEX)) - ); + private static Matcher remoteReindexDescription() { + return allOf(startsWith("reindex from [host="), endsWith(Strings.format("[%s] to [%s]", SOURCE_INDEX, DEST_INDEX))); } private TaskResult getRunningReindex(final TaskId taskId) { @@ -399,7 +422,11 @@ private TaskResult getRunningReindex(final TaskId taskId) { return reindex; } - private void assertRunningReindexTaskExpectedState(final TaskInfo taskInfo, final Matcher expectedTaskDescription) { + private void assertRunningReindexTaskExpectedState( + final TaskInfo taskInfo, + final Matcher expectedTaskDescription, + final int slices + ) { assertThat(taskInfo.action(), equalTo(ReindexAction.NAME)); assertThat(taskInfo.description(), is(expectedTaskDescription)); assertThat(taskInfo.cancelled(), equalTo(false)); @@ -407,19 +434,27 @@ private void assertRunningReindexTaskExpectedState(final TaskInfo taskInfo, fina final BulkByScrollTask.Status taskStatus = ((BulkByScrollTask.Status) taskInfo.status()); // lessThan because the initial running reindex might have "uninitialized" 0 - assertThat(taskStatus.getTotal(), lessThanOrEqualTo((long) NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST)); + assertThat(taskStatus.getTotal(), lessThanOrEqualTo((long) numberOfDocumentsThatTakes60SecondsToIngest)); assertThat(taskStatus.getUpdated(), is(0L)); - assertThat(taskStatus.getCreated(), lessThan((long) NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST)); + assertThat(taskStatus.getCreated(), lessThan((long) numberOfDocumentsThatTakes60SecondsToIngest)); assertThat(taskStatus.getDeleted(), is(0L)); - assertThat(taskStatus.getBatches(), lessThan(NUMBER_OF_DOCUMENTS_THAT_TAKES_60_SECONDS_TO_INGEST)); + assertThat(taskStatus.getBatches(), lessThan((int) Math.ceil((float) numberOfDocumentsThatTakes60SecondsToIngest / bulkSize))); assertThat(taskStatus.getVersionConflicts(), is(0L)); assertThat(taskStatus.getNoops(), is(0L)); assertThat(taskStatus.getBulkRetries(), is(0L)); assertThat(taskStatus.getSearchRetries(), is(0L)); assertThat(taskStatus.getThrottled(), greaterThanOrEqualTo(TimeValue.ZERO)); - assertThat(taskStatus.getRequestsPerSecond(), is(1.0f)); + // sliced leader only reports on completed slices, so the status is completely empty until some slices complete + assertThat(taskStatus.getRequestsPerSecond(), equalTo(slices >= 2 ? 0.0f : requestsPerSecond)); assertThat(taskStatus.getReasonCancelled(), is(nullValue())); assertThat(taskStatus.getThrottledUntil(), greaterThanOrEqualTo(TimeValue.ZERO)); + + if (slices >= 2) { + final List expectedStatuses = Collections.nCopies(slices, null); + assertThat("running slices statuses are null", taskStatus.getSliceStatuses(), equalTo(expectedStatuses)); + } else { + assertThat(taskStatus.getSliceStatuses().isEmpty(), is(true)); + } } private TaskResult getCompletedTaskResult(final TaskId taskId) { @@ -433,11 +468,11 @@ private TaskResult getCompletedTaskResult(final TaskId taskId) { private void createIndexPinnedToNodeName(final String index, final String nodeName) { prepareCreate(index).setSettings( Settings.builder() - .put("index.number_of_shards", 1) + .put("index.number_of_shards", randomIntBetween(1, 3)) .put("index.number_of_replicas", 0) .put("index.routing.allocation.require._name", nodeName) ).get(); - ensureGreen(TimeValue.timeValueSeconds(10), SOURCE_INDEX); + ensureGreen(TimeValue.timeValueSeconds(10), index); } private void unthrottleReindex(final TaskId taskId) { @@ -463,12 +498,40 @@ private String nodeIdByName(final String nodeName) { return nodeWithName; } - private void assertDocCount(final String index, final int expected) throws IOException { - assertNoFailures(indicesAdmin().prepareRefresh(index).get()); - final Request request = new Request("GET", "/" + index + "/_count"); + private TestTelemetryPlugin getTelemetryPlugin(final String nodeName) { + return internalCluster().getInstance(PluginsService.class, nodeName) + .filterPlugins(TestTelemetryPlugin.class) + .findFirst() + .orElseThrow(); + } + + private void assertNoReindexMetricsOnNode(final String nodeName) { + final TestTelemetryPlugin plugin = getTelemetryPlugin(nodeName); + plugin.collect(); + assertThat(plugin.getLongCounterMeasurement(ReindexMetrics.REINDEX_COMPLETION_COUNTER), is(empty())); + assertThat(plugin.getLongHistogramMeasurement(ReindexMetrics.REINDEX_TIME_HISTOGRAM), is(empty())); + } + + private void assertReindexSuccessMetricsOnNode(final String nodeName, final boolean isRemote, final int slices) { + final TestTelemetryPlugin plugin = getTelemetryPlugin(nodeName); + plugin.collect(); + final List completions = plugin.getLongCounterMeasurement(ReindexMetrics.REINDEX_COMPLETION_COUNTER); + assertThat(completions.size(), equalTo(slices)); + for (final Measurement completion : completions) { + assertNull(completion.attributes().get(ReindexMetrics.ATTRIBUTE_NAME_ERROR_TYPE)); + final String expectedSource = isRemote + ? ReindexMetrics.ATTRIBUTE_VALUE_SOURCE_REMOTE + : ReindexMetrics.ATTRIBUTE_VALUE_SOURCE_LOCAL; + assertThat(completion.attributes().get(ReindexMetrics.ATTRIBUTE_NAME_SOURCE), equalTo(expectedSource)); + } + } + + private void assertExpectedNumberOfDocumentsInDestinationIndex() throws IOException { + assertNoFailures(indicesAdmin().prepareRefresh(DEST_INDEX).get()); + final Request request = new Request("GET", "/" + DEST_INDEX + "/_count"); final Response response = getRestClient().performRequest(request); final Map body = ESRestTestCase.entityAsMap(response); final int count = ((Number) body.get("count")).intValue(); - assertThat(count, equalTo(expected)); + assertThat(count, equalTo(numberOfDocumentsThatTakes60SecondsToIngest)); } } diff --git a/modules/reindex/src/main/java/org/elasticsearch/reindex/AbstractAsyncBulkByScrollAction.java b/modules/reindex/src/main/java/org/elasticsearch/reindex/AbstractAsyncBulkByScrollAction.java index 5b87994b9a53b..91aef40aa9156 100644 --- a/modules/reindex/src/main/java/org/elasticsearch/reindex/AbstractAsyncBulkByScrollAction.java +++ b/modules/reindex/src/main/java/org/elasticsearch/reindex/AbstractAsyncBulkByScrollAction.java @@ -557,7 +557,7 @@ void notifyDone(long thisBatchStartTimeNS, ScrollConsumableHitsResponse asyncRes onScrollResponse(asyncResponse); return; } - if (task.isRelocationRequested() && task.isWorker() && task.getParentTaskId().isSet() == false) { + if (task.isRelocationRequested()) { final Optional nodeToRelocateTo = worker.getNodeToRelocateTo(); if (nodeToRelocateTo.isPresent()) { final String scrollId = asyncResponse.response().getScrollId(); @@ -571,10 +571,13 @@ void notifyDone(long thisBatchStartTimeNS, ScrollConsumableHitsResponse asyncRes remoteVersion ); final ResumeInfo resumeInfo = new ResumeInfo(workerResumeInfo, null); - // build response with resume info. everything else doesn't matter since the object is discarded and onFailure is called. + // This response is a local carrier for resumeInfo — for higher-level code to handle relocation and then discard. + // However, status must be accurate for sliced tasks only, the leader state stores this response and derives + // its own combined status from it to serialize to .tasks index. + // For non-sliced, status is unused (comes from the worker state). final BulkByScrollResponse response = new BulkByScrollResponse( TimeValue.MINUS_ONE, - new BulkByScrollTask.Status(List.of(), null), + task.getStatus(), List.of(), List.of(), false, diff --git a/modules/reindex/src/main/java/org/elasticsearch/reindex/Reindexer.java b/modules/reindex/src/main/java/org/elasticsearch/reindex/Reindexer.java index b047963afcfed..0065ccdf49f15 100644 --- a/modules/reindex/src/main/java/org/elasticsearch/reindex/Reindexer.java +++ b/modules/reindex/src/main/java/org/elasticsearch/reindex/Reindexer.java @@ -67,7 +67,9 @@ import org.elasticsearch.script.ReindexScript; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptService; +import org.elasticsearch.tasks.CancellableTask; import org.elasticsearch.tasks.TaskId; +import org.elasticsearch.tasks.TaskManager; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportService; import org.elasticsearch.xcontent.XContentBuilder; @@ -107,6 +109,7 @@ public class Reindexer { private final ScriptService scriptService; private final ReindexSslConfig reindexSslConfig; private final ReindexMetrics reindexMetrics; + private final TaskManager taskManager; private final TransportService transportService; private final ReindexRelocationNodePicker relocationNodePicker; @@ -128,7 +131,8 @@ public class Reindexer { this.scriptService = scriptService; this.reindexSslConfig = reindexSslConfig; this.reindexMetrics = reindexMetrics; - this.transportService = Objects.requireNonNull(transportService); + this.taskManager = transportService.getTaskManager(); // implicit null check + this.transportService = transportService; this.relocationNodePicker = Objects.requireNonNull(relocationNodePicker); } @@ -338,8 +342,8 @@ ActionListener listenerWithRelocations( final ReindexRequest request, final ActionListener listener ) { - final boolean slicedThereforeNoRelocation = task.getParentTaskId().isSet() || task.isLeader(); - if (slicedThereforeNoRelocation) { + final boolean isRelocationHandledByLeader = getReindexParent(task).isPresent(); + if (isRelocationHandledByLeader) { return listener; } return listener.delegateFailureAndWrap((l, response) -> { @@ -349,8 +353,9 @@ ActionListener listenerWithRelocations( l.onResponse(response); return; } - assert task.isWorker() : "relocation only supports non-sliced for now"; - final String nodeToRelocateTo = task.getWorkerState().getNodeToRelocateTo().orElse(null); + final String nodeToRelocateTo = task.isLeader() + ? task.getLeaderState().getNodeToRelocateTo().orElse(null) + : task.getWorkerState().getNodeToRelocateTo().orElse(null); assert nodeToRelocateTo != null : "node to relocate to should be set if taskResumeInfo is present"; final DiscoveryNode nodeToRelocateToNode = clusterService.state().nodes().get(nodeToRelocateTo); if (nodeToRelocateToNode == null) { @@ -384,10 +389,19 @@ private void initTaskForRelocationIfEnabled(final BulkByScrollTask task) { if (ReindexPlugin.REINDEX_RESILIENCE_ENABLED == false) { return; } - final boolean nonSlicedThereforeSetupRelocation = task.isWorker() && task.getParentTaskId().isSet() == false; - if (nonSlicedThereforeSetupRelocation) { - // we don't need a thread-safe nodeToRelocateToSupplier for non-sliced, but re-using leads to less code - task.getWorkerState().setNodeToRelocateToSupplier(new NodeToRelocateToSupplier(clusterService, relocationNodePicker)); + // set up reindex relocation, specifically the supplier which says which node to relocate to. + // we have 3 states to handle: + // 1. leader which has >= 2 subslices: initialized with a centralized node picker. workers will fetch this and use it. + // 2. worker which is one of many subslices: fetch the leader node picker and use it for relocation decisions. + // 3. worker which is the only slice, no leader: set up its own node picker, call that, and when it's done, relocate itself. + // n.b. + // - workers with a leader only need the supplier to see if there is a node to relocate to, therefore, whether they should stop. + // - leader then relocates the entire reindex once workers have completed. + // - approach relies on the entire reindex (including subtasks) existing on the same node. + if (task.isLeader()) { + task.getLeaderState().setNodeToRelocateToSupplier(new NodeToRelocateToSupplier(clusterService, relocationNodePicker)); + } else { + task.getWorkerState().setNodeToRelocateToSupplier(getWorkerNodeToRelocateToSupplier(task)); } } @@ -429,6 +443,29 @@ public Optional get() { } } + /** + * Returns the parent {@link BulkByScrollTask} leader if this task is a worker whose parent will handle relocation on its behalf. + * A parent task ID can also refer to an external caller (e.g. enrich, system migration) -- those don't handle relocation. + * N.b. relies on reindex subtasks existing on the same node as the parent. + */ + private Optional getReindexParent(final BulkByScrollTask task) { + if (task.isWorker() == false || task.getParentTaskId().isSet() == false) { + return Optional.empty(); + } + final CancellableTask parent = taskManager.getCancellableTasks().get(task.getParentTaskId().getId()); + if (parent instanceof BulkByScrollTask parentBbs && parentBbs.isLeader()) { + return Optional.of(parentBbs); + } + return Optional.empty(); + } + + private Supplier> getWorkerNodeToRelocateToSupplier(final BulkByScrollTask workerTask) { + assert workerTask.isWorker() : "task should be a worker"; + return getReindexParent(workerTask).map(leader -> (Supplier>) leader.getLeaderState()::getNodeToRelocateTo) + // we don't need a thread-safe nodeToRelocateToSupplier for non-sliced, but re-using leads to less code + .orElseGet(() -> new NodeToRelocateToSupplier(clusterService, relocationNodePicker)); + } + /** * Build the {@link RestClient} used for reindexing from remote clusters. * @param remoteInfo connection information for the remote cluster diff --git a/modules/reindex/src/test/java/org/elasticsearch/reindex/ReindexerTests.java b/modules/reindex/src/test/java/org/elasticsearch/reindex/ReindexerTests.java index 25e599a9772b0..06e0a43c85526 100644 --- a/modules/reindex/src/test/java/org/elasticsearch/reindex/ReindexerTests.java +++ b/modules/reindex/src/test/java/org/elasticsearch/reindex/ReindexerTests.java @@ -30,6 +30,7 @@ import org.elasticsearch.index.reindex.ResumeReindexAction; import org.elasticsearch.script.ScriptService; import org.elasticsearch.tasks.TaskId; +import org.elasticsearch.tasks.TaskManager; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportResponseHandler; @@ -37,6 +38,7 @@ import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.ExecutorService; @@ -125,10 +127,27 @@ public void testWrapWithMetricsSearchFailure() { // listenerWithRelocations tests - public void testListenerWithRelocationsPassesThroughForWorkerWithParent() { + public void testListenerWithRelocationsPassesThroughForWorkerWithLeaderParent() { assumeTrue("reindex resilience enabled", ReindexPlugin.REINDEX_RESILIENCE_ENABLED); - final Reindexer reindexer = reindexerWithRelocation(); - final BulkByScrollTask task = createTaskWithParentIdAndRelocationEnabled(new TaskId("node", 99)); + final long parentTaskId = 99; + final BulkByScrollTask leaderTask = new BulkByScrollTask( + parentTaskId, + "test_type", + "test_action", + "test", + TaskId.EMPTY_TASK_ID, + Collections.emptyMap(), + true + ); + leaderTask.setWorkerCount(2); + + final TaskManager taskManager = mock(TaskManager.class); + when(taskManager.getCancellableTasks()).thenReturn(Map.of(parentTaskId, leaderTask)); + final TransportService transportService = mock(TransportService.class); + when(transportService.getTaskManager()).thenReturn(taskManager); + + final Reindexer reindexer = reindexerWithRelocation(mock(ClusterService.class), transportService); + final BulkByScrollTask task = createTaskWithParentIdAndRelocationEnabled(new TaskId("node", parentTaskId)); task.setWorker(Float.POSITIVE_INFINITY, null); final ActionListener original = spy(ActionListener.noop()); @@ -294,7 +313,10 @@ private static BulkByScrollTask createTaskWithParentIdAndRelocationEnabled(final } private static Reindexer reindexerWithRelocation() { - return reindexerWithRelocation(mock(ClusterService.class), mock(TransportService.class)); + final TaskManager taskManager = mock(TaskManager.class); + final TransportService transportService = mock(TransportService.class); + when(transportService.getTaskManager()).thenReturn(taskManager); + return reindexerWithRelocation(mock(ClusterService.class), transportService); } private static Reindexer reindexerWithRelocation(ClusterService clusterService, TransportService transportService) { diff --git a/server/src/main/java/org/elasticsearch/index/reindex/LeaderBulkByScrollTaskState.java b/server/src/main/java/org/elasticsearch/index/reindex/LeaderBulkByScrollTaskState.java index 984411ab58276..df6400320692f 100644 --- a/server/src/main/java/org/elasticsearch/index/reindex/LeaderBulkByScrollTaskState.java +++ b/server/src/main/java/org/elasticsearch/index/reindex/LeaderBulkByScrollTaskState.java @@ -9,13 +9,20 @@ package org.elasticsearch.index.reindex; +import org.apache.lucene.util.SetOnce; import org.elasticsearch.action.ActionListener; import org.elasticsearch.common.util.concurrent.AtomicArray; +import org.elasticsearch.core.TimeValue; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; import static java.util.Collections.unmodifiableList; @@ -35,12 +42,14 @@ public class LeaderBulkByScrollTaskState { * How many subtasks are still running */ private final AtomicInteger runningSubtasks; + private final SetOnce>> nodeToRelocateToSupplier; public LeaderBulkByScrollTaskState(BulkByScrollTask task, int slices) { this.task = task; this.slices = slices; results = new AtomicArray<>(slices); runningSubtasks = new AtomicInteger(slices); + this.nodeToRelocateToSupplier = new SetOnce<>(); } /** @@ -105,11 +114,31 @@ public void onSliceFailure(ActionListener listener, int sl // TODO cancel when a slice fails? } + public void setNodeToRelocateToSupplier(Supplier> nodeToRelocateToSupplier) { + this.nodeToRelocateToSupplier.set(Objects.requireNonNull(nodeToRelocateToSupplier)); + } + + public Optional getNodeToRelocateTo() { + final Supplier> supplier = this.nodeToRelocateToSupplier.get(); + if (supplier == null) { + throw new IllegalStateException("Node to relocate to supplier should be set before, if this method is called"); + } + return supplier.get(); + } + private void recordSliceCompletionAndRespondIfAllDone(ActionListener listener) { if (runningSubtasks.decrementAndGet() != 0) { return; } + if (task.isRelocationRequested() && getNodeToRelocateTo().isPresent()) { + final BulkByScrollResponse relocationResponse = relocationResponseIfNeeded().orElse(null); + if (relocationResponse != null) { + listener.onResponse(relocationResponse); + return; + } + } + List responses = new ArrayList<>(results.length()); Exception exception = null; for (Result t : results.asList()) { @@ -132,6 +161,48 @@ private void recordSliceCompletionAndRespondIfAllDone(ActionListener relocationResponseIfNeeded() { + final Map sliceResumeInfoMap = new HashMap<>(); + boolean allJobsCompletedThereforeNoNeedForRelocation = true; + for (final Result result : results.asList()) { + final var sliceStatus = getSliceStatus(result); + if (sliceStatus.resumeInfo() != null) { + allJobsCompletedThereforeNoNeedForRelocation = false; + } + sliceResumeInfoMap.put(result.sliceId, sliceStatus); + } + if (allJobsCompletedThereforeNoNeedForRelocation) { + return Optional.empty(); + } + final var resumeInfo = new ResumeInfo(null, sliceResumeInfoMap); + // this response is a local carrier for resumeInfo only — for higher-level code to handle relocation and then discard. + // the status for the task that's serialized into the .tasks index is taken from the leader state. + return Optional.of( + new BulkByScrollResponse( + TimeValue.MINUS_ONE, + new BulkByScrollTask.Status(List.of(), null), + List.of(), + List.of(), + false, + resumeInfo + ) + ); + } + + private static ResumeInfo.SliceStatus getSliceStatus(final Result result) { + final var workerResumeInfo = Optional.ofNullable(result.response) + .flatMap(BulkByScrollResponse::getTaskResumeInfo) + .flatMap(resumeInfo -> { + assert resumeInfo.worker() != null : "if taskResumeInfo present, worker should have resume info"; + assert resumeInfo.slices() == null : "if taskResumeInfo present, worker shouldn't have slices"; + return resumeInfo.getWorker(); + }) + .orElse(null); + // even if we have slice failure(s), still relocate and run other slices to completion (current functionality without relocations) + final var workerResult = workerResumeInfo == null ? new ResumeInfo.WorkerResult(result.response, result.failure) : null; + return new ResumeInfo.SliceStatus(result.sliceId, workerResumeInfo, workerResult); + } + private static final class Result { final BulkByScrollResponse response; final int sliceId; diff --git a/server/src/main/java/org/elasticsearch/index/reindex/ReindexRequest.java b/server/src/main/java/org/elasticsearch/index/reindex/ReindexRequest.java index b4e53daa4f602..a19d39472a2d0 100644 --- a/server/src/main/java/org/elasticsearch/index/reindex/ReindexRequest.java +++ b/server/src/main/java/org/elasticsearch/index/reindex/ReindexRequest.java @@ -266,6 +266,7 @@ public RemoteInfo getRemoteInfo() { public ReindexRequest forSlice(TaskId slicingTask, SearchRequest slice, int totalSlices) { ReindexRequest sliced = doForSlice(new ReindexRequest(slice, destination, false), slicingTask, totalSlices); sliced.setRemoteInfo(remoteInfo); + sliced.setEligibleForRelocationOnShutdown(isEligibleForRelocationOnShutdown()); return sliced; } diff --git a/server/src/main/java/org/elasticsearch/index/reindex/WorkerBulkByScrollTaskState.java b/server/src/main/java/org/elasticsearch/index/reindex/WorkerBulkByScrollTaskState.java index 675e2e83bb999..14a12b45ada83 100644 --- a/server/src/main/java/org/elasticsearch/index/reindex/WorkerBulkByScrollTaskState.java +++ b/server/src/main/java/org/elasticsearch/index/reindex/WorkerBulkByScrollTaskState.java @@ -184,7 +184,11 @@ public void setNodeToRelocateToSupplier(Supplier> nodeToRelocat } public Optional getNodeToRelocateTo() { - return Objects.requireNonNull(this.nodeToRelocateToSupplier.get(), "nodeToRelocateToSupplier not set for worker").get(); + final Supplier> supplier = this.nodeToRelocateToSupplier.get(); + if (supplier == null) { + throw new IllegalStateException("Node to relocate to supplier should be set before, if this method is called"); + } + return supplier.get(); } float getRequestsPerSecond() { diff --git a/server/src/test/java/org/elasticsearch/index/reindex/LeaderBulkByScrollTaskStateTests.java b/server/src/test/java/org/elasticsearch/index/reindex/LeaderBulkByScrollTaskStateTests.java index dae364911a130..946c0984444ec 100644 --- a/server/src/test/java/org/elasticsearch/index/reindex/LeaderBulkByScrollTaskStateTests.java +++ b/server/src/test/java/org/elasticsearch/index/reindex/LeaderBulkByScrollTaskStateTests.java @@ -10,6 +10,7 @@ package org.elasticsearch.index.reindex; import org.elasticsearch.action.ActionListener; +import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.tasks.TaskId; import org.elasticsearch.test.ESTestCase; import org.junit.Before; @@ -18,6 +19,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Optional; import static java.util.Collections.emptyList; import static org.elasticsearch.core.TimeValue.timeValueMillis; @@ -130,6 +133,188 @@ public void testProgress() { } } + // --- relocation tests --- + + public void testRelocationAllSlicesHaveResumeInfo() { + final int sliceCount = between(2, 5); + final var leaderTask = createRelocationLeaderTask(sliceCount); + final var leaderState = leaderTask.getLeaderState(); + + final BulkByScrollResponse[] sliceResponses = new BulkByScrollResponse[sliceCount]; + final PlainActionFuture future = new PlainActionFuture<>(); + for (int i = 0; i < sliceCount; i++) { + sliceResponses[i] = resumeSliceResponse(i); + final ActionListener listener = i < sliceCount - 1 ? neverCalled() : future; + leaderState.onSliceResponse(listener, i, sliceResponses[i]); + } + + assertTrue(future.isDone()); + final BulkByScrollResponse response = future.actionGet(); + assertTrue(response.getTaskResumeInfo().isPresent()); + final ResumeInfo resumeInfo = response.getTaskResumeInfo().get(); + assertNull(resumeInfo.worker()); + assertNotNull(resumeInfo.slices()); + assertEquals(sliceCount, resumeInfo.slices().size()); + for (int i = 0; i < sliceCount; i++) { + final ResumeInfo.SliceStatus sliceStatus = resumeInfo.slices().get(i); + assertEquals(i, sliceStatus.sliceId()); + assertNull("slice " + i + " should not have a result", sliceStatus.result()); + // resume info should be the same object from the original slice response + assertSame(sliceResponses[i].getTaskResumeInfo().get().worker(), sliceStatus.resumeInfo()); + } + } + + public void testRelocationMixedCompletedAndResumeInfo() { + final int sliceCount = between(3, 6); + final var leaderTask = createRelocationLeaderTask(sliceCount); + final var leaderState = leaderTask.getLeaderState(); + + // the first slice completes normally, the rest have resume info + final BulkByScrollResponse completedResponse = completedSliceResponse(0); + final BulkByScrollResponse[] resumeResponses = new BulkByScrollResponse[sliceCount - 1]; + final PlainActionFuture future = new PlainActionFuture<>(); + leaderState.onSliceResponse(neverCalled(), 0, completedResponse); + for (int i = 1; i < sliceCount; i++) { + resumeResponses[i - 1] = resumeSliceResponse(i); + final ActionListener listener = i < sliceCount - 1 ? neverCalled() : future; + leaderState.onSliceResponse(listener, i, resumeResponses[i - 1]); + } + + assertTrue(future.isDone()); + final BulkByScrollResponse response = future.actionGet(); + assertTrue(response.getTaskResumeInfo().isPresent()); + final ResumeInfo resumeInfo = response.getTaskResumeInfo().get(); + assertEquals(sliceCount, resumeInfo.slices().size()); + + // slice 0 completed normally — should have WorkerResult with the original response, no resumeInfo + final ResumeInfo.SliceStatus slice0 = resumeInfo.slices().get(0); + assertNull(slice0.resumeInfo()); + assertNotNull(slice0.result()); + assertSame(completedResponse, slice0.result().response()); + assertNull(slice0.result().failure()); + + // the remaining slices have resume info matching the original responses + for (int i = 1; i < sliceCount; i++) { + final ResumeInfo.SliceStatus sliceStatus = resumeInfo.slices().get(i); + assertNull("slice " + i + " should not have a result", sliceStatus.result()); + assertSame(resumeResponses[i - 1].getTaskResumeInfo().get().worker(), sliceStatus.resumeInfo()); + } + } + + public void testRelocationAllSlicesCompletedNoResumeInfo() { + final int sliceCount = between(2, 5); + final var leaderTask = createRelocationLeaderTask(sliceCount); + final var leaderState = leaderTask.getLeaderState(); + + // all slices complete normally — relocation should be skipped even though requested + final PlainActionFuture future = new PlainActionFuture<>(); + for (int i = 0; i < sliceCount; i++) { + final ActionListener listener = i < sliceCount - 1 ? neverCalled() : future; + leaderState.onSliceResponse(listener, i, completedSliceResponse(i)); + } + + assertTrue(future.isDone()); + final BulkByScrollResponse response = future.actionGet(); + // should be a normal merged response, no ResumeInfo + assertFalse(response.getTaskResumeInfo().isPresent()); + } + + public void testRelocationMixedFailuresAndResumeInfo() { + final int sliceCount = between(3, 6); + final var leaderTask = createRelocationLeaderTask(sliceCount); + final var leaderState = leaderTask.getLeaderState(); + + // the first slice fails, the remaining have resume info + final RuntimeException sliceFailure = new RuntimeException("slice 0 failed"); + final BulkByScrollResponse[] resumeResponses = new BulkByScrollResponse[sliceCount - 1]; + final PlainActionFuture future = new PlainActionFuture<>(); + leaderState.onSliceFailure(neverCalled(), 0, sliceFailure); + for (int i = 1; i < sliceCount; i++) { + resumeResponses[i - 1] = resumeSliceResponse(i); + final ActionListener listener = i < sliceCount - 1 ? neverCalled() : future; + leaderState.onSliceResponse(listener, i, resumeResponses[i - 1]); + } + + assertTrue(future.isDone()); + final BulkByScrollResponse response = future.actionGet(); + assertTrue(response.getTaskResumeInfo().isPresent()); + final ResumeInfo resumeInfo = response.getTaskResumeInfo().get(); + assertEquals(sliceCount, resumeInfo.slices().size()); + + // slice 0 failed — should have WorkerResult with the original failure + final ResumeInfo.SliceStatus slice0 = resumeInfo.slices().get(0); + assertNull(slice0.resumeInfo()); + assertNotNull(slice0.result()); + assertNull(slice0.result().response()); + assertSame(sliceFailure, slice0.result().failure()); + + // the remaining slices have resume info matching the original responses + for (int i = 1; i < sliceCount; i++) { + final ResumeInfo.SliceStatus sliceStatus = resumeInfo.slices().get(i); + assertNull("slice " + i + " should not have a result", sliceStatus.result()); + assertSame(resumeResponses[i - 1].getTaskResumeInfo().get().worker(), sliceStatus.resumeInfo()); + } + } + + private static BulkByScrollTask createRelocationLeaderTask(final int sliceCount) { + final BulkByScrollTask task = new BulkByScrollTask( + randomNonNegativeLong(), + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10), + TaskId.EMPTY_TASK_ID, + Map.of(), + true + ); + task.setWorkerCount(sliceCount); + task.requestRelocation(); + task.getLeaderState().setNodeToRelocateToSupplier(() -> Optional.of("target-node")); + return task; + } + + private static BulkByScrollTask.Status statusForSlice(final int sliceId) { + return new BulkByScrollTask.Status( + sliceId, + randomNonNegativeInt(), + randomNonNegativeInt(), + randomNonNegativeInt(), + randomNonNegativeInt(), + randomNonNegativeInt(), + randomNonNegativeInt(), + randomNonNegativeInt(), + randomNonNegativeInt(), + randomNonNegativeInt(), + randomTimeValue(), + randomFloat(), + randomBoolean() ? randomAlphaOfLength(5) : null, + randomTimeValue() + ); + + } + + private static BulkByScrollResponse resumeSliceResponse(final int sliceId) { + final var workerStatus = statusForSlice(sliceId); + final var workerResumeInfo = new ResumeInfo.ScrollWorkerResumeInfo( + "scroll-" + sliceId, + randomNonNegativeLong(), + workerStatus, + null + ); + return new BulkByScrollResponse( + randomTimeValue(), + new BulkByScrollTask.Status(List.of(), null), + List.of(), + List.of(), + false, + new ResumeInfo(workerResumeInfo, null) + ); + } + + private static BulkByScrollResponse completedSliceResponse(final int sliceId) { + final var sliceStatus = statusForSlice(sliceId); + return new BulkByScrollResponse(randomTimeValue(), sliceStatus, List.of(), List.of(), false); + } + private ActionListener neverCalled() { return new ActionListener() { @Override From 0769e94a2c3aeb13e8cb51d1e38660b19e22b67d Mon Sep 17 00:00:00 2001 From: David Turner Date: Tue, 3 Mar 2026 18:42:51 +0000 Subject: [PATCH 080/137] Eagerly release resources in `TransportAwaitClusterStateVersionAppliedAction` (#143477) Today `TransportAwaitClusterStateVersionAppliedAction` remains subscribed to the `ClusterApplierService` after cancellation, and this subscription retains a reference to its inner listener even when complete. This commit moves to using a `SubscribableListener`, avoiding retaining the inner listener after completion, and subscribes directly to the `ClusterApplierService` so that it can unsubscribe promptly on cancellation. --- ...aitClusterStateVersionAppliedActionIT.java | 7 +- ...aitClusterStateVersionAppliedResponse.java | 8 +- ...AwaitClusterStateVersionAppliedAction.java | 128 ++++++++++-------- 3 files changed, 80 insertions(+), 63 deletions(-) diff --git a/server/src/internalClusterTest/java/org/elasticsearch/action/admin/cluster/state/TransportAwaitClusterStateVersionAppliedActionIT.java b/server/src/internalClusterTest/java/org/elasticsearch/action/admin/cluster/state/TransportAwaitClusterStateVersionAppliedActionIT.java index 7a8c1563637fe..eecbe2f38c73e 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/action/admin/cluster/state/TransportAwaitClusterStateVersionAppliedActionIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/action/admin/cluster/state/TransportAwaitClusterStateVersionAppliedActionIT.java @@ -194,7 +194,7 @@ public void testTimeout() { assertEquals(0, response.getNodes().size()); } - public void testCancellation() { + public void testCancellation() throws Exception { var currentState = internalCluster().getInstance(ClusterService.class).state(); var future = client().execute( @@ -221,6 +221,11 @@ public void testCancellation() { client().execute(TransportCancelTasksAction.TYPE, cancelRequest); assertThrows(TaskCancelledException.class, () -> future.actionGet(SAFE_AWAIT_TIMEOUT)); + + for (var clusterService : internalCluster().getInstances(ClusterService.class)) { + // assertBusy because we complete the response listener just before unsubscribing + assertBusy(() -> assertEquals(0, clusterService.getClusterApplierService().getTimeoutClusterStateListenersSize())); + } } @Override diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/state/AwaitClusterStateVersionAppliedResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/state/AwaitClusterStateVersionAppliedResponse.java index 864689986c492..3b1f51a596d04 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/state/AwaitClusterStateVersionAppliedResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/state/AwaitClusterStateVersionAppliedResponse.java @@ -10,6 +10,7 @@ package org.elasticsearch.action.admin.cluster.state; import org.elasticsearch.action.FailedNodeException; +import org.elasticsearch.action.support.TransportAction; import org.elasticsearch.action.support.nodes.BaseNodesResponse; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.common.io.stream.StreamInput; @@ -20,9 +21,6 @@ public class AwaitClusterStateVersionAppliedResponse extends BaseNodesResponse< TransportAwaitClusterStateVersionAppliedAction.NodeResponse> { - public AwaitClusterStateVersionAppliedResponse(StreamInput in) throws IOException { - super(in); - } public AwaitClusterStateVersionAppliedResponse( ClusterName clusterName, @@ -34,12 +32,12 @@ public AwaitClusterStateVersionAppliedResponse( @Override protected List readNodesFrom(StreamInput in) throws IOException { - return in.readCollectionAsList(TransportAwaitClusterStateVersionAppliedAction.NodeResponse::new); + return TransportAction.localOnly(); } @Override protected void writeNodesTo(StreamOutput out, List nodes) throws IOException { - out.writeCollection(nodes); + TransportAction.localOnly(); } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportAwaitClusterStateVersionAppliedAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportAwaitClusterStateVersionAppliedAction.java index 738739bb5ffca..2017319f0eec8 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportAwaitClusterStateVersionAppliedAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportAwaitClusterStateVersionAppliedAction.java @@ -11,20 +11,21 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.elasticsearch.ElasticsearchTimeoutException; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionType; import org.elasticsearch.action.FailedNodeException; import org.elasticsearch.action.support.ActionFilters; +import org.elasticsearch.action.support.SubscribableListener; import org.elasticsearch.action.support.nodes.BaseNodeResponse; import org.elasticsearch.action.support.nodes.TransportNodesAction; -import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.ClusterStateObserver; +import org.elasticsearch.cluster.ClusterChangedEvent; +import org.elasticsearch.cluster.TimeoutClusterStateListener; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.core.TimeValue; import org.elasticsearch.injection.guice.Inject; import org.elasticsearch.node.NodeClosedException; @@ -39,8 +40,7 @@ import java.io.IOException; import java.util.List; import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Predicate; +import java.util.function.Consumer; /** * An action that waits for a given cluster state version to be applied on provided set of nodes in the cluster. @@ -99,74 +99,92 @@ protected NodeResponse newNodeResponse(StreamInput in, DiscoveryNode node) throw @Override protected NodeResponse nodeOperation(NodeRequest request, Task task) { /// We are using [#nodeOperationAsync]. + logger.error("expected nodeOperationAsync"); + assert false : "nodeOperationAsync"; throw new UnsupportedOperationException(); } - @Override - protected void nodeOperationAsync(NodeRequest request, Task task, ActionListener listener) { - var completed = new AtomicBoolean(false); + private class VersionAppliedListener implements TimeoutClusterStateListener { - var cancellableTask = (CancellableTask) task; - cancellableTask.addListener(() -> { - if (completed.compareAndSet(false, true)) { - listener.onFailure(new TaskCancelledException(cancellableTask.getReasonCancelled())); - } - }); + private final long clusterStateVersion; + private final Consumer cancelSubscriber; + private final ActionListener listener; - Predicate predicate = (ClusterState state) -> cancellableTask.isCancelled() - || state.version() >= request.clusterStateVersion; + VersionAppliedListener(long clusterStateVersion, Consumer cancelSubscriber, ActionListener listener) { + this.clusterStateVersion = clusterStateVersion; + this.cancelSubscriber = cancelSubscriber; + this.listener = listener; + } - var clusterStateListener = new ClusterStateObserver.Listener() { - @Override - public void onNewClusterState(ClusterState state) { - // The listener is notified directly from the task in case of cancellation. - if (completed.compareAndSet(false, true)) { - listener.onResponse(new NodeResponse(clusterService.localNode())); - } + @Override + public void postAdded() { + if (clusterService.state().version() >= clusterStateVersion) { + removeListener(); + listener.onResponse(null); + } else { + cancelSubscriber.accept(VersionAppliedListener.this::removeListener); } + } - @Override - public void onClusterServiceClose() { - // The listener is notified directly from the task in case of cancellation. - if (completed.compareAndSet(false, true)) { - listener.onFailure(new NodeClosedException(clusterService.localNode())); - } - } + private void removeListener() { + clusterService.getClusterApplierService().removeTimeoutListener(VersionAppliedListener.this); + } - @Override - public void onTimeout(TimeValue timeout) { - // The listener is notified directly from the task in case of cancellation. - if (completed.compareAndSet(false, true)) { - listener.onFailure( - new ElasticsearchTimeoutException( - "timed out waiting for cluster state version [" + request.clusterStateVersion + "] to be applied" - ) - ); - } + @Override + public void onClose() { + removeListener(); + listener.onFailure(new NodeClosedException(clusterService.localNode())); + } + + @Override + public void onTimeout(TimeValue timeout) { + logger.error("no timeout configured"); + assert false : "no timeout configured"; + } + + @Override + public void clusterChanged(ClusterChangedEvent event) { + if (event.state().version() >= clusterStateVersion) { + removeListener(); + listener.onResponse(null); } - }; + } + } - ClusterStateObserver.waitForState( - clusterService, - threadPool.getThreadContext(), - clusterStateListener, - predicate, - request.timeout == TimeValue.MINUS_ONE ? null : request.timeout, - logger - ); + @Override + protected void nodeOperationAsync(NodeRequest request, Task task, ActionListener listener) { + final var onceListener = new SubscribableListener(); + onceListener.addListener(listener.map(ignored -> new NodeResponse(clusterService.localNode()))); + + if (request.timeout != TimeValue.MINUS_ONE) { + onceListener.addTimeout(request.timeout, threadPool, EsExecutors.DIRECT_EXECUTOR_SERVICE); + } + + final var cancellableTask = (CancellableTask) task; + cancellableTask.addListener(() -> onceListener.onFailure(new TaskCancelledException(cancellableTask.getReasonCancelled()))); + + clusterService.getClusterApplierService() + .addTimeoutListener( + null, + new VersionAppliedListener( + request.clusterStateVersion, + r -> onceListener.addListener(ActionListener.running(r)), + onceListener + ) + ); } public static class NodeRequest extends AbstractTransportRequest { private final long clusterStateVersion; private final TimeValue timeout; - public NodeRequest(StreamInput in) throws IOException { + NodeRequest(StreamInput in) throws IOException { super(in); this.clusterStateVersion = in.readLong(); this.timeout = in.readTimeValue(); } - public NodeRequest(long clusterStateVersion, TimeValue timeout) { + NodeRequest(long clusterStateVersion, TimeValue timeout) { this.clusterStateVersion = clusterStateVersion; this.timeout = timeout; } @@ -190,15 +208,11 @@ public String getDescription() { } public static class NodeResponse extends BaseNodeResponse { - public NodeResponse(StreamInput in, DiscoveryNode node) throws IOException { + NodeResponse(StreamInput in, DiscoveryNode node) throws IOException { super(in, node); } - public NodeResponse(StreamInput in) throws IOException { - super(in); - } - - public NodeResponse(DiscoveryNode node) { + NodeResponse(DiscoveryNode node) { super(node); } } From 6ec8d9210141bb5644ba596bb28be4eda45aca86 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Tue, 3 Mar 2026 13:47:31 -0500 Subject: [PATCH 081/137] ESQL: Remaining serialization tests (#143470) This adds the remaining serialization tests. It makes a few production code changes: 1. Registers `TO_DATE_RANGE` for serialization. It was serializable and not registered. 2. Normalizes the serialization of `SCORE` and explains how it used to work. It was not broken but held together strangely. 3. Replaces implementing `SurrogateExpression` with `OnlySurrogateExpression` in a few more cases so we don't expect serialization to work. 4. Adds some package private accessors so we can refer to children by name in serialization tests. --- .../esql/expression/ExpressionWritables.java | 2 + .../aggregate/PercentileOverTime.java | 4 +- .../function/aggregate/StddevOverTime.java | 4 +- .../function/aggregate/VarianceOverTime.java | 4 +- .../expression/function/fulltext/Score.java | 24 +++++-- .../scalar/convert/ToIntegerSurrogate.java | 4 +- .../function/scalar/convert/ToIp.java | 4 +- .../scalar/convert/ToLongSurrogate.java | 4 +- .../function/scalar/score/Decay.java | 16 +++++ .../function/EsqlFunctionRegistryTests.java | 54 ++-------------- .../AbsentOverTimeSerializationTests.java | 18 ++++++ ...meSeriesAggregationSerializationTests.java | 43 +++++++++++++ .../AvgOverTimeSerializationTests.java | 18 ++++++ ...untDistinctOverTimeSerializationTests.java | 42 ++++++++++++ .../CountOverTimeSerializationTests.java | 18 ++++++ .../aggregate/DeltaSerializationTests.java | 42 ++++++++++++ .../aggregate/DerivSerializationTests.java | 42 ++++++++++++ .../FirstOverTimeSerializationTests.java | 42 ++++++++++++ .../aggregate/IdeltaSerializationTests.java | 42 ++++++++++++ .../aggregate/IrateSerializationTests.java | 42 ++++++++++++ .../LastOverTimeSerializationTests.java | 42 ++++++++++++ .../MaxOverTimeSerializationTests.java | 18 ++++++ .../MinOverTimeSerializationTests.java | 18 ++++++ .../PresentOverTimeSerializationTests.java | 18 ++++++ .../SumOverTimeSerializationTests.java | 18 ++++++ .../aggregate/VarianceSerializationTests.java | 35 ++++++++++ .../fulltext/KqlSerializationTests.java | 30 +++++++++ .../MatchPhraseSerializationTests.java | 37 +++++++++++ .../fulltext/MatchSerializationTests.java | 37 +++++++++++ .../MultiMatchSerializationTests.java | 38 +++++++++++ .../QueryStringSerializationTests.java | 30 +++++++++ .../fulltext/ScoreSerializationTests.java | 30 +++++++++ ...gregateMetricDoubleSerializationTests.java | 19 ++++++ .../ToDateRangeSerializationTests.java | 19 ++++++ .../ToDenseVectorSerializationTests.java | 19 ++++++ .../convert/ToTDigestSerializationTests.java | 19 ++++++ .../multivalue/MvUnionSerializationTests.java | 37 +++++++++++ .../scalar/score/DecaySerializationTests.java | 64 +++++++++++++++++++ .../spatial/StGeohexSerializationTests.java | 39 +++++++++++ .../spatial/StGeotileSerializationTests.java | 39 +++++++++++ .../spatial/StNPointsSerializationTests.java | 27 ++++++++ .../spatial/StXMaxSerializationTests.java | 27 ++++++++ .../spatial/StXMinSerializationTests.java | 27 ++++++++ .../spatial/StYMaxSerializationTests.java | 27 ++++++++ .../spatial/StYMinSerializationTests.java | 27 ++++++++ .../string/TopSnippetsSerializationTests.java | 57 +++++++++++++++++ .../CosineSimilaritySerializationTests.java | 18 ++++++ 47 files changed, 1218 insertions(+), 67 deletions(-) create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AbsentOverTimeSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AbstractTimeSeriesAggregationSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AvgOverTimeSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountDistinctOverTimeSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountOverTimeSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/DeltaSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/DerivSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/FirstOverTimeSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/IdeltaSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/IrateSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/LastOverTimeSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MaxOverTimeSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MinOverTimeSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/PresentOverTimeSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SumOverTimeSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/VarianceSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/KqlSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchPhraseSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MultiMatchSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/QueryStringSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToAggregateMetricDoubleSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDateRangeSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDenseVectorSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToTDigestSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvUnionSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/score/DecaySerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StNPointsSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StXMaxSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StXMinSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StYMaxSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StYMinSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/TopSnippetsSerializationTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/vector/CosineSimilaritySerializationTests.java diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java index 6f34526ec7467..fa9b7af8463c6 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java @@ -23,6 +23,7 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToCartesianPoint; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToCartesianShape; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDateNanos; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDateRange; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDatetime; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDegrees; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDenseVector; @@ -230,6 +231,7 @@ public static List unaryScalars() { entries.add(ToCartesianPoint.ENTRY); entries.add(ToDatetime.ENTRY); entries.add(ToDateNanos.ENTRY); + entries.add(ToDateRange.ENTRY); entries.add(ToDegrees.ENTRY); entries.add(ToDenseVector.ENTRY); entries.add(ToDouble.ENTRY); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/PercentileOverTime.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/PercentileOverTime.java index 710bdb65def68..4952635cbe14e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/PercentileOverTime.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/PercentileOverTime.java @@ -13,7 +13,7 @@ import org.elasticsearch.xpack.esql.core.tree.NodeInfo; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.expression.SurrogateExpression; +import org.elasticsearch.xpack.esql.expression.OnlySurrogateExpression; import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesTo; import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesToLifecycle; @@ -27,7 +27,7 @@ /** * Similar to {@link Percentile}, but it is used to calculate the percentile value over a time series of values from the given field. */ -public class PercentileOverTime extends TimeSeriesAggregateFunction implements SurrogateExpression, ToAggregator { +public class PercentileOverTime extends TimeSeriesAggregateFunction implements OnlySurrogateExpression, ToAggregator { @FunctionInfo( returnType = "double", description = "Calculates the percentile over time of a field.", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/StddevOverTime.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/StddevOverTime.java index 8519a780f409e..af2416b99a728 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/StddevOverTime.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/StddevOverTime.java @@ -13,7 +13,7 @@ import org.elasticsearch.xpack.esql.core.tree.NodeInfo; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.expression.SurrogateExpression; +import org.elasticsearch.xpack.esql.expression.OnlySurrogateExpression; import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesTo; import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesToLifecycle; @@ -30,7 +30,7 @@ /** * Similar to {@link StdDev}, but it is used to calculate the standard deviation over a time series of values from the given field. */ -public class StddevOverTime extends TimeSeriesAggregateFunction implements SurrogateExpression, ToAggregator { +public class StddevOverTime extends TimeSeriesAggregateFunction implements OnlySurrogateExpression, ToAggregator { @FunctionInfo( returnType = "double", description = "Calculates the population standard deviation over time of a numeric field.", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/VarianceOverTime.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/VarianceOverTime.java index 99130796ad740..08f7e171e1424 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/VarianceOverTime.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/VarianceOverTime.java @@ -13,7 +13,7 @@ import org.elasticsearch.xpack.esql.core.tree.NodeInfo; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.expression.SurrogateExpression; +import org.elasticsearch.xpack.esql.expression.OnlySurrogateExpression; import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesTo; import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesToLifecycle; @@ -30,7 +30,7 @@ /** * Similar to {@link Variance}, but it is used to calculate the variance over a time series of values from the given field. */ -public class VarianceOverTime extends TimeSeriesAggregateFunction implements SurrogateExpression, ToAggregator { +public class VarianceOverTime extends TimeSeriesAggregateFunction implements OnlySurrogateExpression, ToAggregator { @FunctionInfo( returnType = "double", description = "Calculates the population variance over time of a numeric field.", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java index 0e7fd2bd1287c..b001b3eb00d58 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java @@ -59,11 +59,7 @@ public Score( description = "Boolean expression that contains full text function(s) to be scored." ) Expression scorableQuery ) { - this(source, List.of(scorableQuery)); - } - - protected Score(Source source, List children) { - super(source, children); + super(source, List.of(scorableQuery)); } @Override @@ -73,7 +69,7 @@ public DataType dataType() { @Override public Expression replaceChildren(List newChildren) { - return new Score(source(), newChildren); + return new Score(source(), newChildren.getFirst()); } @Override @@ -95,12 +91,26 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(EvaluatorMapper.ToEv @Override public void writeTo(StreamOutput out) throws IOException { source().writeTo(out); - out.writeNamedWriteableCollection(this.children()); + out.writeOptionalNamedWriteable(children().getFirst()); } private static Expression readFrom(StreamInput in) throws IOException { Source source = Source.readFrom((PlanStreamInput) in); + /* + * This is not truly optional. But when the SCORE scalar was originally + * created we serialized it with this pair: + * + * in.readOptionalNamedWriteable(Expression.class); + * out.writeNamedWriteableCollection(this.children()); + * + * This pair *is* compatible if we send a single element list. Single + * element lists are serialized as `0x01 `. That's also + * how optional named writeables are serialized. + */ Expression query = in.readOptionalNamedWriteable(Expression.class); + if (query == null) { + throw new IllegalStateException("query isn't really optional"); + } return new Score(source, query); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIntegerSurrogate.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIntegerSurrogate.java index 37ec7167faf0b..6e33dcab03045 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIntegerSurrogate.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIntegerSurrogate.java @@ -14,7 +14,7 @@ import org.elasticsearch.xpack.esql.core.tree.NodeInfo; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.expression.SurrogateExpression; +import org.elasticsearch.xpack.esql.expression.OnlySurrogateExpression; import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.OptionalArgument; @@ -43,7 +43,7 @@ * */ -public class ToIntegerSurrogate extends EsqlScalarFunction implements SurrogateExpression, OptionalArgument, ConvertFunction { +public class ToIntegerSurrogate extends EsqlScalarFunction implements OnlySurrogateExpression, OptionalArgument, ConvertFunction { private final Expression field; private final Expression base; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIp.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIp.java index 4b4514e7e2437..4c44d705c4291 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIp.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToIp.java @@ -16,7 +16,7 @@ import org.elasticsearch.xpack.esql.core.tree.NodeInfo; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.expression.SurrogateExpression; +import org.elasticsearch.xpack.esql.expression.OnlySurrogateExpression; import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.MapParam; @@ -62,7 +62,7 @@ * expose a single method to users. *

*/ -public class ToIp extends EsqlScalarFunction implements SurrogateExpression, OptionalArgument, ConvertFunction { +public class ToIp extends EsqlScalarFunction implements OnlySurrogateExpression, OptionalArgument, ConvertFunction { private static final String LEADING_ZEROS = "leading_zeros"; public static final Map ALLOWED_OPTIONS = Map.ofEntries(Map.entry(LEADING_ZEROS, KEYWORD)); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongSurrogate.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongSurrogate.java index 1fdcf6a7d54db..e217c6be0ae67 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongSurrogate.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongSurrogate.java @@ -14,7 +14,7 @@ import org.elasticsearch.xpack.esql.core.tree.NodeInfo; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.expression.SurrogateExpression; +import org.elasticsearch.xpack.esql.expression.OnlySurrogateExpression; import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.OptionalArgument; @@ -46,7 +46,7 @@ * */ -public class ToLongSurrogate extends EsqlScalarFunction implements SurrogateExpression, OptionalArgument, ConvertFunction { +public class ToLongSurrogate extends EsqlScalarFunction implements OnlySurrogateExpression, OptionalArgument, ConvertFunction { private final Expression field; private final Expression base; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/score/Decay.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/score/Decay.java index c1f65c1fa2b93..2b09b3ba7813c 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/score/Decay.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/score/Decay.java @@ -210,6 +210,22 @@ public String getWriteableName() { return ENTRY.name; } + Expression value() { + return value; + } + + Expression origin() { + return origin; + } + + Expression scale() { + return scale; + } + + Expression options() { + return options; + } + @Override protected TypeResolution resolveType() { if (childrenResolved() == false) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistryTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistryTests.java index c8f7a7ac11b49..3ed4cbf0f1abc 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistryTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistryTests.java @@ -19,7 +19,9 @@ import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; import org.elasticsearch.xpack.esql.expression.OnlySurrogateExpression; +import org.elasticsearch.xpack.esql.expression.function.inference.InferenceFunction; import org.elasticsearch.xpack.esql.expression.function.scalar.EsqlConfigurationFunction; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.FoldablesConvertFunction; import org.elasticsearch.xpack.esql.parser.ParsingException; import org.elasticsearch.xpack.esql.session.Configuration; @@ -241,7 +243,10 @@ public void testRegisteredFunctionHaveTests() { for (FunctionDefinition def : registry.listFunctions()) { checkFunctionTestExists(errors, def, "Tests", AbstractFunctionTestCase.class); checkFunctionTestExists(errors, def, "ErrorTests", ErrorsForCasesWithoutExamplesTestCase.class); - if (false == OnlySurrogateExpression.class.isAssignableFrom(def.clazz())) { + boolean isSerializable = false == OnlySurrogateExpression.class.isAssignableFrom(def.clazz()) + && false == FoldablesConvertFunction.class.isAssignableFrom(def.clazz()) + && false == InferenceFunction.class.isAssignableFrom(def.clazz()); + if (isSerializable) { checkFunctionTestExists(errors, def, "SerializationTests", AbstractExpressionSerializationTests.class); } } @@ -253,63 +258,38 @@ public void testRegisteredFunctionHaveTests() { * while working on something, but released stuff should not have an entry here. */ matchesList().item("org.elasticsearch.xpack.esql.expression.function.aggregate.AbsentOverTimeErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.AbsentOverTimeSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.AvgOverTimeErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.AvgOverTimeSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.CountDistinctErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.CountDistinctOverTimeErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.CountDistinctOverTimeSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.CountOverTimeErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.CountOverTimeSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.DeltaErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.DeltaSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.DerivErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.DerivSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.FirstErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.FirstOverTimeErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.FirstOverTimeSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.IdeltaErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.IdeltaSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.IncreaseErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.IrateErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.IrateSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.LastErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.LastOverTimeErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.LastOverTimeSerializationTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.MaxOverTimeSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.MedianAbsoluteDeviationErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.MedianErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.MinOverTimeSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.PercentileOverTimeErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.PercentileOverTimeSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.PresentOverTimeErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.PresentOverTimeSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.RateErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.SpatialCentroidErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.SpatialExtentErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.StdDevErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.StddevOverTimeErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.StddevOverTimeSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.SumErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.SumOverTimeErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.SumOverTimeSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.VarianceErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.VarianceOverTimeErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.VarianceOverTimeSerializationTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.aggregate.VarianceSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.aggregate.WeightedAvgErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.fulltext.KqlSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.fulltext.MatchPhraseErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.fulltext.MatchPhraseSerializationTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.fulltext.MatchSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.fulltext.MultiMatchErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.fulltext.MultiMatchSerializationTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.fulltext.QueryStringSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.fulltext.ScoreErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.fulltext.ScoreSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.grouping.BucketErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.grouping.TBucketErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.inference.TextEmbeddingSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.ClampErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.ClampTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.conditional.ClampMaxErrorTests is missing") @@ -317,21 +297,10 @@ public void testRegisteredFunctionHaveTests() { .item("org.elasticsearch.xpack.esql.expression.function.scalar.conditional.GreatestErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.conditional.LeastErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToAggregateMetricDoubleErrorTests is missing") - .item( - "org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToAggregateMetricDoubleSerializationTests is missing" - ) - .item("org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDatePeriodSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDateRangeErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDateRangeSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDateRangeTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDenseVectorErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDenseVectorSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeohexErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToIntegerSurrogateSerializationTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToIpSerializationTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToLongSurrogateSerializationTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToTDigestSerializationTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToTimeDurationSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToVersionErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.date.NowErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.math.AcoshErrorTests is missing") @@ -345,27 +314,16 @@ public void testRegisteredFunctionHaveTests() { .item("org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvIntersectionErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvSortErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvUnionErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvUnionSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.nulls.CoalesceErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.score.DecayErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.score.DecaySerializationTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexSerializationTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StNPointsErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StNPointsSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StSimplifyErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StXMaxSerializationTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StXMinSerializationTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StYMaxSerializationTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StYMinSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.string.ChunkErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.string.ContainsErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.string.TopSnippetsErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.scalar.string.TopSnippetsSerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.util.DelayErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.scalar.util.DelayTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.vector.CosineSimilarityErrorTests is missing") - .item("org.elasticsearch.xpack.esql.expression.function.vector.CosineSimilaritySerializationTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.vector.DotProductErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.vector.HammingErrorTests is missing") .item("org.elasticsearch.xpack.esql.expression.function.vector.KnnErrorTests is missing") diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AbsentOverTimeSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AbsentOverTimeSerializationTests.java new file mode 100644 index 0000000000000..5542be8af4acf --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AbsentOverTimeSerializationTests.java @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; + +public class AbsentOverTimeSerializationTests extends AbstractTimeSeriesAggregationSerializationTests { + @Override + protected AbsentOverTime create(Source source, Expression field, Expression filter, Expression window) { + return new AbsentOverTime(source, field, filter, window); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AbstractTimeSeriesAggregationSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AbstractTimeSeriesAggregationSerializationTests.java new file mode 100644 index 0000000000000..0caca2464167b --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AbstractTimeSeriesAggregationSerializationTests.java @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +/** + * Helper for making serialization tests for time series aggregations that take + * {@code field}, {@code filter}, and {@code window}. + */ +public abstract class AbstractTimeSeriesAggregationSerializationTests extends + AbstractExpressionSerializationTests { + + protected abstract T create(Source source, Expression field, Expression filter, Expression window); + + @Override + protected final T createTestInstance() { + return create(randomSource(), randomChild(), randomChild(), randomChild()); + } + + @Override + protected final T mutateInstance(T instance) throws IOException { + Source source = instance.source(); + Expression field = instance.field(); + Expression filter = instance.filter(); + Expression window = instance.window(); + switch (between(0, 2)) { + case 0 -> field = randomValueOtherThan(field, AbstractExpressionSerializationTests::randomChild); + case 1 -> filter = randomValueOtherThan(filter, AbstractExpressionSerializationTests::randomChild); + case 2 -> window = randomValueOtherThan(window, AbstractExpressionSerializationTests::randomChild); + } + return create(source, field, filter, window); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AvgOverTimeSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AvgOverTimeSerializationTests.java new file mode 100644 index 0000000000000..41602086c87a6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AvgOverTimeSerializationTests.java @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; + +public class AvgOverTimeSerializationTests extends AbstractTimeSeriesAggregationSerializationTests { + @Override + protected AvgOverTime create(Source source, Expression field, Expression filter, Expression window) { + return new AvgOverTime(source, field, filter, window); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountDistinctOverTimeSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountDistinctOverTimeSerializationTests.java new file mode 100644 index 0000000000000..16fa302f2a722 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountDistinctOverTimeSerializationTests.java @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class CountDistinctOverTimeSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected CountDistinctOverTime createTestInstance() { + Source source = randomSource(); + Expression field = randomChild(); + Expression filter = randomChild(); + Expression window = randomChild(); + Expression precision = randomBoolean() ? null : randomChild(); + return new CountDistinctOverTime(source, field, filter, window, precision); + } + + @Override + protected CountDistinctOverTime mutateInstance(CountDistinctOverTime instance) throws IOException { + Source source = instance.source(); + Expression field = instance.field(); + Expression filter = instance.filter(); + Expression window = instance.window(); + Expression precision = instance.parameters().isEmpty() ? null : instance.parameters().getFirst(); + switch (between(0, 3)) { + case 0 -> field = randomValueOtherThan(field, AbstractExpressionSerializationTests::randomChild); + case 1 -> filter = randomValueOtherThan(filter, AbstractExpressionSerializationTests::randomChild); + case 2 -> window = randomValueOtherThan(window, AbstractExpressionSerializationTests::randomChild); + case 3 -> precision = randomValueOtherThan(precision, () -> randomBoolean() ? null : randomChild()); + } + return new CountDistinctOverTime(source, field, filter, window, precision); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountOverTimeSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountOverTimeSerializationTests.java new file mode 100644 index 0000000000000..e2fe4387912d3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountOverTimeSerializationTests.java @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; + +public class CountOverTimeSerializationTests extends AbstractTimeSeriesAggregationSerializationTests { + @Override + protected CountOverTime create(Source source, Expression field, Expression filter, Expression window) { + return new CountOverTime(source, field, filter, window); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/DeltaSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/DeltaSerializationTests.java new file mode 100644 index 0000000000000..72ba39be1e6bd --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/DeltaSerializationTests.java @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class DeltaSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected Delta createTestInstance() { + Source source = randomSource(); + Expression field = randomChild(); + Expression filter = randomChild(); + Expression window = randomChild(); + Expression timestamp = randomChild(); + return new Delta(source, field, filter, window, timestamp); + } + + @Override + protected Delta mutateInstance(Delta instance) throws IOException { + Source source = instance.source(); + Expression field = instance.field(); + Expression filter = instance.filter(); + Expression window = instance.window(); + Expression timestamp = instance.timestamp(); + switch (between(0, 3)) { + case 0 -> field = randomValueOtherThan(field, AbstractExpressionSerializationTests::randomChild); + case 1 -> filter = randomValueOtherThan(filter, AbstractExpressionSerializationTests::randomChild); + case 2 -> window = randomValueOtherThan(window, AbstractExpressionSerializationTests::randomChild); + case 3 -> timestamp = randomValueOtherThan(timestamp, AbstractExpressionSerializationTests::randomChild); + } + return new Delta(source, field, filter, window, timestamp); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/DerivSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/DerivSerializationTests.java new file mode 100644 index 0000000000000..184f61cb430d6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/DerivSerializationTests.java @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class DerivSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected Deriv createTestInstance() { + Source source = randomSource(); + Expression field = randomChild(); + Expression filter = randomChild(); + Expression window = randomChild(); + Expression timestamp = randomChild(); + return new Deriv(source, field, filter, window, timestamp); + } + + @Override + protected Deriv mutateInstance(Deriv instance) throws IOException { + Source source = instance.source(); + Expression field = instance.field(); + Expression filter = instance.filter(); + Expression window = instance.window(); + Expression timestamp = instance.timestamp(); + switch (between(0, 3)) { + case 0 -> field = randomValueOtherThan(field, AbstractExpressionSerializationTests::randomChild); + case 1 -> filter = randomValueOtherThan(filter, AbstractExpressionSerializationTests::randomChild); + case 2 -> window = randomValueOtherThan(window, AbstractExpressionSerializationTests::randomChild); + case 3 -> timestamp = randomValueOtherThan(timestamp, AbstractExpressionSerializationTests::randomChild); + } + return new Deriv(source, field, filter, window, timestamp); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/FirstOverTimeSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/FirstOverTimeSerializationTests.java new file mode 100644 index 0000000000000..69f441f50828c --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/FirstOverTimeSerializationTests.java @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class FirstOverTimeSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected FirstOverTime createTestInstance() { + Source source = randomSource(); + Expression field = randomChild(); + Expression filter = randomChild(); + Expression window = randomChild(); + Expression timestamp = randomChild(); + return new FirstOverTime(source, field, filter, window, timestamp); + } + + @Override + protected FirstOverTime mutateInstance(FirstOverTime instance) throws IOException { + Source source = instance.source(); + Expression field = instance.field(); + Expression filter = instance.filter(); + Expression window = instance.window(); + Expression timestamp = instance.timestamp(); + switch (between(0, 3)) { + case 0 -> field = randomValueOtherThan(field, AbstractExpressionSerializationTests::randomChild); + case 1 -> filter = randomValueOtherThan(filter, AbstractExpressionSerializationTests::randomChild); + case 2 -> window = randomValueOtherThan(window, AbstractExpressionSerializationTests::randomChild); + case 3 -> timestamp = randomValueOtherThan(timestamp, AbstractExpressionSerializationTests::randomChild); + } + return new FirstOverTime(source, field, filter, window, timestamp); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/IdeltaSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/IdeltaSerializationTests.java new file mode 100644 index 0000000000000..6a8e8a84a2765 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/IdeltaSerializationTests.java @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class IdeltaSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected Idelta createTestInstance() { + Source source = randomSource(); + Expression field = randomChild(); + Expression filter = randomChild(); + Expression window = randomChild(); + Expression timestamp = randomChild(); + return new Idelta(source, field, filter, window, timestamp); + } + + @Override + protected Idelta mutateInstance(Idelta instance) throws IOException { + Source source = instance.source(); + Expression field = instance.field(); + Expression filter = instance.filter(); + Expression window = instance.window(); + Expression timestamp = instance.timestamp(); + switch (between(0, 3)) { + case 0 -> field = randomValueOtherThan(field, AbstractExpressionSerializationTests::randomChild); + case 1 -> filter = randomValueOtherThan(filter, AbstractExpressionSerializationTests::randomChild); + case 2 -> window = randomValueOtherThan(window, AbstractExpressionSerializationTests::randomChild); + case 3 -> timestamp = randomValueOtherThan(timestamp, AbstractExpressionSerializationTests::randomChild); + } + return new Idelta(source, field, filter, window, timestamp); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/IrateSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/IrateSerializationTests.java new file mode 100644 index 0000000000000..e3eea9a468d20 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/IrateSerializationTests.java @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class IrateSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected Irate createTestInstance() { + Source source = randomSource(); + Expression field = randomChild(); + Expression filter = randomChild(); + Expression window = randomChild(); + Expression timestamp = randomChild(); + return new Irate(source, field, filter, window, timestamp); + } + + @Override + protected Irate mutateInstance(Irate instance) throws IOException { + Source source = instance.source(); + Expression field = instance.field(); + Expression filter = instance.filter(); + Expression window = instance.window(); + Expression timestamp = instance.timestamp(); + switch (between(0, 3)) { + case 0 -> field = randomValueOtherThan(field, AbstractExpressionSerializationTests::randomChild); + case 1 -> filter = randomValueOtherThan(filter, AbstractExpressionSerializationTests::randomChild); + case 2 -> window = randomValueOtherThan(window, AbstractExpressionSerializationTests::randomChild); + case 3 -> timestamp = randomValueOtherThan(timestamp, AbstractExpressionSerializationTests::randomChild); + } + return new Irate(source, field, filter, window, timestamp); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/LastOverTimeSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/LastOverTimeSerializationTests.java new file mode 100644 index 0000000000000..5174f0bd825ef --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/LastOverTimeSerializationTests.java @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class LastOverTimeSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected LastOverTime createTestInstance() { + Source source = randomSource(); + Expression field = randomChild(); + Expression filter = randomChild(); + Expression window = randomChild(); + Expression timestamp = randomChild(); + return new LastOverTime(source, field, filter, window, timestamp); + } + + @Override + protected LastOverTime mutateInstance(LastOverTime instance) throws IOException { + Source source = instance.source(); + Expression field = instance.field(); + Expression filter = instance.filter(); + Expression window = instance.window(); + Expression timestamp = instance.timestamp(); + switch (between(0, 3)) { + case 0 -> field = randomValueOtherThan(field, AbstractExpressionSerializationTests::randomChild); + case 1 -> filter = randomValueOtherThan(filter, AbstractExpressionSerializationTests::randomChild); + case 2 -> window = randomValueOtherThan(window, AbstractExpressionSerializationTests::randomChild); + case 3 -> timestamp = randomValueOtherThan(timestamp, AbstractExpressionSerializationTests::randomChild); + } + return new LastOverTime(source, field, filter, window, timestamp); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MaxOverTimeSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MaxOverTimeSerializationTests.java new file mode 100644 index 0000000000000..2d34d127d7868 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MaxOverTimeSerializationTests.java @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; + +public class MaxOverTimeSerializationTests extends AbstractTimeSeriesAggregationSerializationTests { + @Override + protected MaxOverTime create(Source source, Expression field, Expression filter, Expression window) { + return new MaxOverTime(source, field, filter, window); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MinOverTimeSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MinOverTimeSerializationTests.java new file mode 100644 index 0000000000000..4adfeaa8c78c2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MinOverTimeSerializationTests.java @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; + +public class MinOverTimeSerializationTests extends AbstractTimeSeriesAggregationSerializationTests { + @Override + protected MinOverTime create(Source source, Expression field, Expression filter, Expression window) { + return new MinOverTime(source, field, filter, window); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/PresentOverTimeSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/PresentOverTimeSerializationTests.java new file mode 100644 index 0000000000000..9a413a29a6c61 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/PresentOverTimeSerializationTests.java @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; + +public class PresentOverTimeSerializationTests extends AbstractTimeSeriesAggregationSerializationTests { + @Override + protected PresentOverTime create(Source source, Expression field, Expression filter, Expression window) { + return new PresentOverTime(source, field, filter, window); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SumOverTimeSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SumOverTimeSerializationTests.java new file mode 100644 index 0000000000000..7c9fe33bc8a06 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SumOverTimeSerializationTests.java @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; + +public class SumOverTimeSerializationTests extends AbstractTimeSeriesAggregationSerializationTests { + @Override + protected SumOverTime create(Source source, Expression field, Expression filter, Expression window) { + return new SumOverTime(source, field, filter, window); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/VarianceSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/VarianceSerializationTests.java new file mode 100644 index 0000000000000..362297f8085ad --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/VarianceSerializationTests.java @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.aggregate; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class VarianceSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected Variance createTestInstance() { + return new Variance(randomSource(), randomChild(), randomChild(), randomChild()); + } + + @Override + protected Variance mutateInstance(Variance instance) throws IOException { + Source source = instance.source(); + Expression field = instance.field(); + Expression filter = instance.filter(); + Expression window = instance.window(); + switch (between(0, 2)) { + case 0 -> field = randomValueOtherThan(field, AbstractExpressionSerializationTests::randomChild); + case 1 -> filter = randomValueOtherThan(filter, AbstractExpressionSerializationTests::randomChild); + case 2 -> window = randomValueOtherThan(window, AbstractExpressionSerializationTests::randomChild); + } + return new Variance(source, field, filter, window); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/KqlSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/KqlSerializationTests.java new file mode 100644 index 0000000000000..c09f3fa066bf0 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/KqlSerializationTests.java @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.fulltext; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class KqlSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected Kql createTestInstance() { + Source source = randomSource(); + Expression query = randomChild(); + return new Kql(source, query, null, configuration()); + } + + @Override + protected Kql mutateInstance(Kql instance) throws IOException { + Source source = instance.source(); + Expression query = randomValueOtherThan(instance.query(), AbstractExpressionSerializationTests::randomChild); + return new Kql(source, query, null, configuration()); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchPhraseSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchPhraseSerializationTests.java new file mode 100644 index 0000000000000..0cefd6944eb26 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchPhraseSerializationTests.java @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.fulltext; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class MatchPhraseSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected MatchPhrase createTestInstance() { + Source source = randomSource(); + Expression field = randomChild(); + Expression query = randomChild(); + return new MatchPhrase(source, field, query, null); + } + + @Override + protected MatchPhrase mutateInstance(MatchPhrase instance) throws IOException { + Source source = instance.source(); + Expression field = instance.field(); + Expression query = instance.query(); + if (randomBoolean()) { + field = randomValueOtherThan(field, AbstractExpressionSerializationTests::randomChild); + } else { + query = randomValueOtherThan(query, AbstractExpressionSerializationTests::randomChild); + } + return new MatchPhrase(source, field, query, null); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchSerializationTests.java new file mode 100644 index 0000000000000..ef6821a369038 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchSerializationTests.java @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.fulltext; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class MatchSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected Match createTestInstance() { + Source source = randomSource(); + Expression field = randomChild(); + Expression query = randomChild(); + return new Match(source, field, query, null); + } + + @Override + protected Match mutateInstance(Match instance) throws IOException { + Source source = instance.source(); + Expression field = instance.field(); + Expression query = instance.query(); + if (randomBoolean()) { + field = randomValueOtherThan(field, AbstractExpressionSerializationTests::randomChild); + } else { + query = randomValueOtherThan(query, AbstractExpressionSerializationTests::randomChild); + } + return new Match(source, field, query, null); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MultiMatchSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MultiMatchSerializationTests.java new file mode 100644 index 0000000000000..2df793b316bf7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MultiMatchSerializationTests.java @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.fulltext; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; +import java.util.List; + +public class MultiMatchSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected MultiMatch createTestInstance() { + Source source = randomSource(); + Expression query = randomChild(); + List fields = randomList(1, 5, AbstractExpressionSerializationTests::randomChild); + return new MultiMatch(source, query, fields, null); + } + + @Override + protected MultiMatch mutateInstance(MultiMatch instance) throws IOException { + Source source = instance.source(); + Expression query = instance.query(); + List fields = instance.fields(); + if (randomBoolean()) { + query = randomValueOtherThan(query, AbstractExpressionSerializationTests::randomChild); + } else { + fields = randomValueOtherThan(fields, () -> randomList(1, 5, AbstractExpressionSerializationTests::randomChild)); + } + return new MultiMatch(source, query, fields, null); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/QueryStringSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/QueryStringSerializationTests.java new file mode 100644 index 0000000000000..2c7707b1ad6c0 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/QueryStringSerializationTests.java @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.fulltext; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class QueryStringSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected QueryString createTestInstance() { + Source source = randomSource(); + Expression query = randomChild(); + return new QueryString(source, query, null, configuration()); + } + + @Override + protected QueryString mutateInstance(QueryString instance) throws IOException { + Source source = instance.source(); + Expression query = randomValueOtherThan(instance.query(), AbstractExpressionSerializationTests::randomChild); + return new QueryString(source, query, null, configuration()); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreSerializationTests.java new file mode 100644 index 0000000000000..6aa0b785dab2e --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreSerializationTests.java @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.fulltext; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class ScoreSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected Score createTestInstance() { + Source source = randomSource(); + Expression query = randomChild(); + return new Score(source, query); + } + + @Override + protected Score mutateInstance(Score instance) throws IOException { + Source source = instance.source(); + Expression query = randomValueOtherThan(instance.children().getFirst(), AbstractExpressionSerializationTests::randomChild); + return new Score(source, query); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToAggregateMetricDoubleSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToAggregateMetricDoubleSerializationTests.java new file mode 100644 index 0000000000000..ca2f0b56f79d3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToAggregateMetricDoubleSerializationTests.java @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToAggregateMetricDoubleSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToAggregateMetricDouble create(Source source, Expression child) { + return new ToAggregateMetricDouble(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDateRangeSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDateRangeSerializationTests.java new file mode 100644 index 0000000000000..09136fab9d2ea --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDateRangeSerializationTests.java @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToDateRangeSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToDateRange create(Source source, Expression child) { + return new ToDateRange(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDenseVectorSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDenseVectorSerializationTests.java new file mode 100644 index 0000000000000..56ff05c548378 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToDenseVectorSerializationTests.java @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToDenseVectorSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToDenseVector create(Source source, Expression child) { + return new ToDenseVector(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToTDigestSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToTDigestSerializationTests.java new file mode 100644 index 0000000000000..d3e948921d017 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToTDigestSerializationTests.java @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToTDigestSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToTDigest create(Source source, Expression child) { + return new ToTDigest(source, child); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvUnionSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvUnionSerializationTests.java new file mode 100644 index 0000000000000..fd85435100dc8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvUnionSerializationTests.java @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.multivalue; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class MvUnionSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected MvUnion createTestInstance() { + Source source = randomSource(); + Expression field1 = randomChild(); + Expression field2 = randomChild(); + return new MvUnion(source, field1, field2); + } + + @Override + protected MvUnion mutateInstance(MvUnion instance) throws IOException { + Source source = instance.source(); + Expression left = instance.left(); + Expression right = instance.right(); + if (randomBoolean()) { + left = randomValueOtherThan(left, AbstractExpressionSerializationTests::randomChild); + } else { + right = randomValueOtherThan(right, AbstractExpressionSerializationTests::randomChild); + } + return new MvUnion(source, left, right); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/score/DecaySerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/score/DecaySerializationTests.java new file mode 100644 index 0000000000000..64caba790887e --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/score/DecaySerializationTests.java @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.score; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.expression.Literal; +import org.elasticsearch.xpack.esql.core.expression.MapExpression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class DecaySerializationTests extends AbstractExpressionSerializationTests { + @Override + protected Decay createTestInstance() { + Source source = randomSource(); + Expression value = randomChild(); + Expression origin = randomChild(); + Expression scale = randomChild(); + Expression options = randomBoolean() ? null : randomOptions(); + return new Decay(source, value, origin, scale, options); + } + + @Override + protected Decay mutateInstance(Decay instance) throws IOException { + Source source = instance.source(); + Expression value = instance.value(); + Expression origin = instance.origin(); + Expression scale = instance.scale(); + Expression options = instance.options(); + switch (between(0, 3)) { + case 0 -> value = randomValueOtherThan(value, AbstractExpressionSerializationTests::randomChild); + case 1 -> origin = randomValueOtherThan(origin, AbstractExpressionSerializationTests::randomChild); + case 2 -> scale = randomValueOtherThan(scale, AbstractExpressionSerializationTests::randomChild); + case 3 -> options = randomValueOtherThan(options, () -> randomBoolean() ? null : randomOptions()); + } + return new Decay(source, value, origin, scale, options); + } + + private MapExpression randomOptions() { + List entries = new ArrayList<>(); + if (randomBoolean()) { + entries.add(Literal.keyword(Source.EMPTY, "offset")); + entries.add(new Literal(Source.EMPTY, randomDoubleBetween(0, 100, true), DataType.DOUBLE)); + } + if (randomBoolean()) { + entries.add(Literal.keyword(Source.EMPTY, "decay")); + entries.add(new Literal(Source.EMPTY, randomDoubleBetween(0.01, 0.99, true), DataType.DOUBLE)); + } + if (randomBoolean()) { + entries.add(Literal.keyword(Source.EMPTY, "type")); + entries.add(Literal.keyword(Source.EMPTY, randomFrom("linear", "exp", "gauss"))); + } + return new MapExpression(Source.EMPTY, entries); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexSerializationTests.java new file mode 100644 index 0000000000000..6b57251ba6c77 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexSerializationTests.java @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class StGeohexSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected StGeohex createTestInstance() { + Source source = randomSource(); + Expression field = randomChild(); + Expression precision = randomChild(); + Expression bounds = randomBoolean() ? null : randomChild(); + return new StGeohex(source, field, precision, bounds); + } + + @Override + protected StGeohex mutateInstance(StGeohex instance) throws IOException { + Source source = instance.source(); + Expression field = instance.spatialField(); + Expression precision = instance.parameter(); + Expression bounds = instance.bounds(); + switch (between(0, 2)) { + case 0 -> field = randomValueOtherThan(field, AbstractExpressionSerializationTests::randomChild); + case 1 -> precision = randomValueOtherThan(precision, AbstractExpressionSerializationTests::randomChild); + case 2 -> bounds = randomValueOtherThan(bounds, () -> randomBoolean() ? null : randomChild()); + } + return new StGeohex(source, field, precision, bounds); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileSerializationTests.java new file mode 100644 index 0000000000000..c223f4afa01b5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileSerializationTests.java @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class StGeotileSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected StGeotile createTestInstance() { + Source source = randomSource(); + Expression field = randomChild(); + Expression precision = randomChild(); + Expression bounds = randomBoolean() ? null : randomChild(); + return new StGeotile(source, field, precision, bounds); + } + + @Override + protected StGeotile mutateInstance(StGeotile instance) throws IOException { + Source source = instance.source(); + Expression field = instance.spatialField(); + Expression precision = instance.parameter(); + Expression bounds = instance.bounds(); + switch (between(0, 2)) { + case 0 -> field = randomValueOtherThan(field, AbstractExpressionSerializationTests::randomChild); + case 1 -> precision = randomValueOtherThan(precision, AbstractExpressionSerializationTests::randomChild); + case 2 -> bounds = randomValueOtherThan(bounds, () -> randomBoolean() ? null : randomChild()); + } + return new StGeotile(source, field, precision, bounds); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StNPointsSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StNPointsSerializationTests.java new file mode 100644 index 0000000000000..da29805f89fc0 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StNPointsSerializationTests.java @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class StNPointsSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected StNPoints createTestInstance() { + return new StNPoints(randomSource(), randomChild()); + } + + @Override + protected StNPoints mutateInstance(StNPoints instance) throws IOException { + return new StNPoints( + instance.source(), + randomValueOtherThan(instance.spatialField(), AbstractExpressionSerializationTests::randomChild) + ); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StXMaxSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StXMaxSerializationTests.java new file mode 100644 index 0000000000000..a349c4c8fe3e3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StXMaxSerializationTests.java @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class StXMaxSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected StXMax createTestInstance() { + return new StXMax(randomSource(), randomChild()); + } + + @Override + protected StXMax mutateInstance(StXMax instance) throws IOException { + return new StXMax( + instance.source(), + randomValueOtherThan(instance.spatialField(), AbstractExpressionSerializationTests::randomChild) + ); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StXMinSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StXMinSerializationTests.java new file mode 100644 index 0000000000000..5a75b3cbae32d --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StXMinSerializationTests.java @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class StXMinSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected StXMin createTestInstance() { + return new StXMin(randomSource(), randomChild()); + } + + @Override + protected StXMin mutateInstance(StXMin instance) throws IOException { + return new StXMin( + instance.source(), + randomValueOtherThan(instance.spatialField(), AbstractExpressionSerializationTests::randomChild) + ); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StYMaxSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StYMaxSerializationTests.java new file mode 100644 index 0000000000000..ea064a05f73ba --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StYMaxSerializationTests.java @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class StYMaxSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected StYMax createTestInstance() { + return new StYMax(randomSource(), randomChild()); + } + + @Override + protected StYMax mutateInstance(StYMax instance) throws IOException { + return new StYMax( + instance.source(), + randomValueOtherThan(instance.spatialField(), AbstractExpressionSerializationTests::randomChild) + ); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StYMinSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StYMinSerializationTests.java new file mode 100644 index 0000000000000..4ae5044982c97 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StYMinSerializationTests.java @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; + +public class StYMinSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected StYMin createTestInstance() { + return new StYMin(randomSource(), randomChild()); + } + + @Override + protected StYMin mutateInstance(StYMin instance) throws IOException { + return new StYMin( + instance.source(), + randomValueOtherThan(instance.spatialField(), AbstractExpressionSerializationTests::randomChild) + ); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/TopSnippetsSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/TopSnippetsSerializationTests.java new file mode 100644 index 0000000000000..288242bd46311 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/TopSnippetsSerializationTests.java @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.string; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.expression.Literal; +import org.elasticsearch.xpack.esql.core.expression.MapExpression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class TopSnippetsSerializationTests extends AbstractExpressionSerializationTests { + @Override + protected TopSnippets createTestInstance() { + Source source = randomSource(); + Expression field = randomChild(); + Expression query = randomChild(); + Expression options = randomBoolean() ? null : randomOptions(); + return new TopSnippets(source, field, query, options); + } + + @Override + protected TopSnippets mutateInstance(TopSnippets instance) throws IOException { + Source source = instance.source(); + Expression field = instance.field(); + Expression query = instance.query(); + Expression options = instance.options(); + switch (between(0, 2)) { + case 0 -> field = randomValueOtherThan(field, AbstractExpressionSerializationTests::randomChild); + case 1 -> query = randomValueOtherThan(query, AbstractExpressionSerializationTests::randomChild); + case 2 -> options = randomValueOtherThan(options, () -> randomBoolean() ? null : randomOptions()); + } + return new TopSnippets(source, field, query, options); + } + + private MapExpression randomOptions() { + List entries = new ArrayList<>(); + if (randomBoolean()) { + entries.add(Literal.keyword(Source.EMPTY, "num_snippets")); + entries.add(new Literal(Source.EMPTY, randomIntBetween(1, 20), DataType.INTEGER)); + } + if (randomBoolean()) { + entries.add(Literal.keyword(Source.EMPTY, "num_words")); + entries.add(new Literal(Source.EMPTY, randomIntBetween(1, 1000), DataType.INTEGER)); + } + return new MapExpression(Source.EMPTY, entries); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/vector/CosineSimilaritySerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/vector/CosineSimilaritySerializationTests.java new file mode 100644 index 0000000000000..21f6be00124a4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/vector/CosineSimilaritySerializationTests.java @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.vector; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; + +public class CosineSimilaritySerializationTests extends AbstractVectorSimilaritySerializationTests { + @Override + protected CosineSimilarity create(Source source, Expression left, Expression right) { + return new CosineSimilarity(source, left, right); + } +} From 8e77757e5daed5c6d8562699d30a0d600f52edd4 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 4 Mar 2026 10:18:44 +0200 Subject: [PATCH 082/137] Fix changelog --- docs/changelog/143460.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/changelog/143460.yaml b/docs/changelog/143460.yaml index 082eda2e68ed9..35a4e2a4930c3 100644 --- a/docs/changelog/143460.yaml +++ b/docs/changelog/143460.yaml @@ -1,6 +1,5 @@ area: ES|QL -issues: - - 141920 +issues: [141920, 141925] pr: 143460 summary: Prevent pushdown of unmapped fields in filters and sorts -type: "bug, feature" +type: "bug" From 0f0ae8af43273057417de890453962882c4b5057 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 4 Mar 2026 18:45:02 +0200 Subject: [PATCH 083/137] Fix required caps --- .../src/main/resources/unmapped-load.csv-spec | 43 +++---------------- 1 file changed, 6 insertions(+), 37 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index 35a3a7503d107..aa51efc2ff7e3 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -3,7 +3,7 @@ #################### // These ones verify we don't do anything extra when unmapped_fields is not set to "load" doesNotLoadUnmappedFieldsSort -required_capability: unmapped_fields +required_capability: optional_fields_v2 FROM partial_mapping_sample_data | SORT @timestamp DESC ; @@ -19,7 +19,7 @@ FROM partial_mapping_sample_data ; doesNotLoadUnmappedFieldsStats -required_capability: unmapped_fields +required_capability: optional_fields_v2 FROM partial_mapping_sample_data | STATS count(*) BY message | SORT message @@ -34,8 +34,7 @@ count(*):long | message:keyword ; doesNotLoadUnmappedFieldsInlineStats -required_capability: unmapped_fields -required_capability: inline_stats +required_capability: optional_fields_v2 FROM partial_mapping_sample_data | INLINE STATS count = COUNT(*) BY message | SORT @timestamp DESC @@ -49,9 +48,7 @@ FROM partial_mapping_sample_data ; doesNotLoadUnmappedFieldsInlineStatsNoGrouping -required_capability: unmapped_fields -required_capability: inline_stats -FROM partial_mapping_sample_data +required_capability: optional_fields_v2 | INLINE STATS max_duration = MAX(event_duration) | SORT @timestamp DESC | LIMIT 3 @@ -64,7 +61,7 @@ FROM partial_mapping_sample_data ; doesNotLoadUnmappedFieldsEnrich -required_capability: unmapped_fields +required_capability: optional_fields_v2 required_capability: enrich_load FROM partial_mapping_sample_data | EVAL language_code = 1 @@ -80,7 +77,7 @@ FROM partial_mapping_sample_data ; doesNotLoadUnmappedFieldsLookupJoin -required_capability: unmapped_fields +required_capability: optional_fields_v2 required_capability: join_lookup_v12 FROM partial_mapping_sample_data | EVAL language_code = 1 @@ -100,7 +97,6 @@ FROM partial_mapping_sample_data ###################### fieldIsMappedToNonKeywordSingleIndex -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -120,7 +116,6 @@ FROM partial_mapping_sample_data ; fieldIsMappedToKeywordSingleIndex -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -140,7 +135,6 @@ FROM partial_mapping_sample_data ; unmappedFieldDoesNotAppearLast -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -154,7 +148,6 @@ FROM partial_mapping_sample_data ; fieldDoesNotExistSingleIndex -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -174,7 +167,6 @@ FROM partial_mapping_sample_data ; fieldIsUnmappedSingleIndex -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -197,7 +189,6 @@ FROM partial_mapping_sample_data # up at all. fieldIsUnmappedButSourceIsDisabledSingleIndex-Ignore required_capability: source_field_mapping -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -217,7 +208,6 @@ FROM partial_mapping_no_source_sample_data # same comment as above (fieldIsUnmappedButSourceIsDisabledSingleIndex) fieldIsUnmappedButExcludedFromSourceSingleIndex-Ignore required_capability: source_field_mapping -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -236,7 +226,6 @@ FROM partial_mapping_excluded_source_sample_data ; fieldIsNestedAndMapped -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -252,7 +241,6 @@ Amsterdam ; fieldIsNestedAndMappedNoKeep -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -267,7 +255,6 @@ Europe |Milky Way |Earth ; fieldIsNestedAndUnmapped -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -287,7 +274,6 @@ FROM partial_mapping_sample_data ; fieldIsNestedAndNonExistent -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -311,7 +297,6 @@ FROM partial_mapping_sample_data ######################### noFieldExistsMultiParametersSingleIndex -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -331,7 +316,6 @@ FROM partial_mapping_sample_data ; mixedFieldsMultiParametersSingleIndex -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -351,7 +335,6 @@ FROM partial_mapping_sample_data ; repeatedInsistFieldsUseTheLastEntry -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -375,7 +358,6 @@ FROM partial_mapping_sample_data ##################### mixedFieldsMultiParametersMultiIndex -required_capability: unmapped_fields required_capability: index_metadata_field required_capability: optional_fields_v2 @@ -403,7 +385,6 @@ sample_data | 2023-10-23T12:15:03.360Z | null | Connected ; insistOnTopOfInsistMultiIndex -required_capability: unmapped_fields required_capability: index_metadata_field required_capability: optional_fields_v2 @@ -432,7 +413,6 @@ sample_data | 2023-10-23T12:15:03.360Z | null | Connected fieldDoesNotExistMultiIndex required_capability: index_metadata_field -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -460,7 +440,6 @@ sample_data | 2023-10-23T12:15:03.360Z | null fieldIsUnmappedMultiIndex required_capability: index_metadata_field -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -489,7 +468,6 @@ FROM partial_mapping_sample_data, sample_data METADATA _index fieldIsMappedToDifferentTypesMultiIndex required_capability: index_metadata_field -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -517,7 +495,6 @@ sample_data_ts_long | null fieldIsMappedToDifferentTypesButDropped required_capability: index_metadata_field -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -547,7 +524,6 @@ sample_data_ts_long | 42 fieldIsPartiallyUnmappedMultiIndex required_capability: index_metadata_field -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -574,7 +550,6 @@ sample_data | Connected to 10.1.0.1 ; fieldIsPartiallyUnmappedAndRenamedMultiIndex -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -604,7 +579,6 @@ Connected to 10.1.0.1 fieldIsPartiallyUnmappedPartiallySourceIsDisabledMultiIndex required_capability: index_metadata_field required_capability: source_field_mapping -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -633,7 +607,6 @@ partial_mapping_sample_data | 2024-10-23T13:55:01.543Z | Connected to partialMappingStats required_capability: index_metadata_field required_capability: source_field_mapping -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -654,7 +627,6 @@ max(@timestamp):date | count(*):long | message:keyword partialMappingCoalesce required_capability: index_metadata_field required_capability: source_field_mapping -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -685,7 +657,6 @@ FROM partial_mapping_sample_data,partial_mapping_excluded_source_sample_data MET partialMappingUnionTypes required_capability: index_metadata_field required_capability: source_field_mapping -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; @@ -713,9 +684,7 @@ FROM partial_mapping_sample_data,partial_mapping_excluded_source_sample_data MET ; partialMappingStatsAfterCast -required_capability: index_metadata_field required_capability: source_field_mapping -required_capability: unmapped_fields required_capability: optional_fields_v2 SET unmapped_fields="load"\; From fea828cfb47ac2c0ee077f26935a8299a1fb8beb Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 4 Mar 2026 21:51:35 +0200 Subject: [PATCH 084/137] Fix deleted line --- .../qa/testFixtures/src/main/resources/unmapped-load.csv-spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index aa51efc2ff7e3..8d609f8f8d28b 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -49,6 +49,8 @@ FROM partial_mapping_sample_data doesNotLoadUnmappedFieldsInlineStatsNoGrouping required_capability: optional_fields_v2 + +FROM partial_mapping_sample_data | INLINE STATS max_duration = MAX(event_duration) | SORT @timestamp DESC | LIMIT 3 From 28f67fd938d6089ad5a7781415542cfbef229baa Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 4 Mar 2026 23:50:32 +0200 Subject: [PATCH 085/137] Fix hasIndexMetadata for queries with SET before FROM Replace command parsing with regex that checks whole query for METADATA _index. Use static Pattern to avoid recompilation. Made-with: Cursor --- .../elasticsearch/xpack/esql/ccq/MultiClusterSpecIT.java | 9 +++------ 1 file changed, 3 insertions(+), 6 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 184af4d9a7b17..34091ac8521a3 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 @@ -388,13 +388,10 @@ static boolean canUseRemoteIndicesOnly() { return dataLocation == DataLocation.REMOTE_ONLY && Clusters.bwcVersion().onOrAfter(Version.V_9_1_0); } + private static final Pattern HAS_INDEX_METADATA = Pattern.compile("(?i)metadata\\s+[^|]*_index"); + static boolean hasIndexMetadata(String query) { - String[] commands = query.split("\\|"); - if (commands[0].trim().toLowerCase(Locale.ROOT).startsWith("from")) { - String[] parts = commands[0].split("(?i)metadata"); - return parts.length > 1 && parts[1].contains("_index"); - } - return false; + return HAS_INDEX_METADATA.matcher(query).find(); } @Override From 10e1ff195cd4eaacc3be4d52e6877336d95e2ac9 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Wed, 4 Mar 2026 22:08:26 +0000 Subject: [PATCH 086/137] [CI] Auto commit changes from spotless --- .../org/elasticsearch/xpack/esql/ccq/MultiClusterSpecIT.java | 1 - 1 file changed, 1 deletion(-) 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 34091ac8521a3..81936c33c48dd 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 @@ -38,7 +38,6 @@ import java.io.IOException; import java.net.URL; import java.util.List; -import java.util.Locale; import java.util.Set; import java.util.regex.Pattern; From be4b80bd56f34f3b0ce15b98581837711fb0d312 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 5 Mar 2026 11:53:24 +0200 Subject: [PATCH 087/137] Fix test by adding sort --- .../testFixtures/src/main/resources/unmapped-load.csv-spec | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index 8d609f8f8d28b..8a3b243717ea6 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -709,15 +709,16 @@ SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data METADATA _index | KEEP _index, message | WHERE STARTS_WITH(message, "Connection error") +| SORT _index ; _index:keyword | message:keyword -sample_data | Connection error -sample_data | Connection error -sample_data | Connection error no_mapping_sample_data | Connection error? no_mapping_sample_data | Connection error? no_mapping_sample_data | Connection error? +sample_data | Connection error +sample_data | Connection error +sample_data | Connection error ; sortOnPartiallyUnmappedField From 1db923f2ffa45fa23b1efb12a201fd6aad938684 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 5 Mar 2026 11:53:19 +0200 Subject: [PATCH 088/137] More strict regex --- .../org/elasticsearch/xpack/esql/ccq/MultiClusterSpecIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 81936c33c48dd..9aaf349013911 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 @@ -387,7 +387,7 @@ static boolean canUseRemoteIndicesOnly() { return dataLocation == DataLocation.REMOTE_ONLY && Clusters.bwcVersion().onOrAfter(Version.V_9_1_0); } - private static final Pattern HAS_INDEX_METADATA = Pattern.compile("(?i)metadata\\s+[^|]*_index"); + private static final Pattern HAS_INDEX_METADATA = Pattern.compile("metadata\\s+[^|=]*_index", Pattern.CASE_INSENSITIVE); static boolean hasIndexMetadata(String query) { return HAS_INDEX_METADATA.matcher(query).find(); From 3ef066d6b6ff25d51a58e8cf51a0c196fb742270 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 3 Mar 2026 22:31:57 +0200 Subject: [PATCH 089/137] Analyzer golden tests Made-with: Cursor --- .../src/main/resources/data/all-types.csv | 7 +- .../main/resources/unmapped-nullify.csv-spec | 106 ++++ .../xpack/esql/action/EsqlCapabilities.java | 5 + .../xpack/esql/core/expression/Alias.java | 2 +- .../xpack/esql/core/expression/Attribute.java | 2 +- .../esql/core/expression/FieldAttribute.java | 10 + .../elasticsearch/xpack/esql/CsvTests.java | 10 +- .../analysis/AnalyzerUnmappedGoldenTests.java | 491 ++++++++++++++++++ .../esql/analysis/AnalyzerUnmappedTests.java | 53 ++ .../xpack/esql/optimizer/GoldenTestCase.java | 10 + .../TestPhysicalOperationProviders.java | 38 +- .../testCoalesce/load/analysis.expected | 4 + .../testCoalesce/load/query.esql | 3 + .../testCoalesce/nullify/analysis.expected | 5 + .../testCoalesce/nullify/query.esql | 3 + .../load/analysis.expected | 3 + .../load/query.esql | 2 + .../nullify/analysis.expected | 3 + .../nullify/query.esql | 2 + .../load/analysis.expected | 4 + .../load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../load/analysis.expected | 5 + .../load/query.esql | 3 + .../nullify/analysis.expected | 6 + .../nullify/query.esql | 3 + .../testDrop/load/analysis.expected | 3 + .../testDrop/load/query.esql | 2 + .../testDrop/nullify/analysis.expected | 4 + .../testDrop/nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../testDropAndMatchingStar/load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../testEval/load/analysis.expected | 3 + .../testEval/load/query.esql | 2 + .../testEval/nullify/analysis.expected | 4 + .../testEval/nullify/query.esql | 2 + .../load/analysis.expected | 5 + .../testEvalAfterKeepStar/load/query.esql | 4 + .../nullify/analysis.expected | 6 + .../testEvalAfterKeepStar/nullify/query.esql | 4 + .../load/analysis.expected | 5 + .../load/query.esql | 4 + .../nullify/analysis.expected | 6 + .../nullify/query.esql | 4 + .../testEvalAndKeep/load/analysis.expected | 4 + .../testEvalAndKeep/load/query.esql | 3 + .../testEvalAndKeep/nullify/analysis.expected | 5 + .../testEvalAndKeep/nullify/query.esql | 3 + .../testEvalCast/load/analysis.expected | 3 + .../testEvalCast/load/query.esql | 2 + .../testEvalCast/nullify/analysis.expected | 4 + .../testEvalCast/nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../testEvalCastInPlace/load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../testEvalCastInPlace/nullify/query.esql | 2 + .../testEvalReplace/load/analysis.expected | 4 + .../testEvalReplace/load/query.esql | 3 + .../testEvalReplace/nullify/analysis.expected | 5 + .../testEvalReplace/nullify/query.esql | 3 + .../testFork/load/analysis.expected | 13 + .../testFork/load/query.esql | 3 + .../testFork/nullify/analysis.expected | 14 + .../testFork/nullify/query.esql | 3 + .../testForkWithEval/load/analysis.expected | 14 + .../testForkWithEval/load/query.esql | 3 + .../nullify/analysis.expected | 15 + .../testForkWithEval/nullify/query.esql | 3 + .../testForkWithStats/load/analysis.expected | 15 + .../testForkWithStats/load/query.esql | 4 + .../nullify/analysis.expected | 16 + .../testForkWithStats/nullify/query.esql | 4 + .../testFuse/load/analysis.expected | 15 + .../testFuse/load/query.esql | 4 + .../testFuse/nullify/analysis.expected | 16 + .../testFuse/nullify/query.esql | 4 + .../testFuseLinear/load/analysis.expected | 18 + .../testFuseLinear/load/query.esql | 4 + .../testFuseLinear/nullify/analysis.expected | 19 + .../testFuseLinear/nullify/query.esql | 4 + .../testFuseWithEval/load/analysis.expected | 16 + .../testFuseWithEval/load/query.esql | 4 + .../nullify/analysis.expected | 17 + .../testFuseWithEval/nullify/query.esql | 4 + .../testInlineStats/load/analysis.expected | 4 + .../testInlineStats/load/query.esql | 2 + .../testInlineStats/nullify/analysis.expected | 5 + .../testInlineStats/nullify/query.esql | 2 + .../testKeep/load/analysis.expected | 4 + .../testKeep/load/query.esql | 3 + .../testKeep/nullify/analysis.expected | 5 + .../testKeep/nullify/query.esql | 3 + .../load/analysis.expected | 3 + .../testKeepAndMatchingStar/load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../testKeepRepeated/load/analysis.expected | 3 + .../testKeepRepeated/load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../testKeepRepeated/nullify/query.esql | 2 + .../testKeepThenEval/load/analysis.expected | 4 + .../testKeepThenEval/load/query.esql | 3 + .../nullify/analysis.expected | 5 + .../testKeepThenEval/nullify/query.esql | 3 + .../testLookupJoin/load/analysis.expected | 5 + .../testLookupJoin/load/query.esql | 3 + .../testLookupJoin/nullify/analysis.expected | 6 + .../testLookupJoin/nullify/query.esql | 3 + .../load/analysis.expected | 6 + .../testLookupJoinWithFilter/load/query.esql | 4 + .../nullify/analysis.expected | 7 + .../nullify/query.esql | 4 + .../load/analysis.expected | 3 + .../testMappedInOneIndexOnly/load/query.esql | 2 + .../nullify/analysis.expected | 3 + .../nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../load/query.esql | 2 + .../nullify/analysis.expected | 3 + .../nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../load/query.esql | 2 + .../nullify/analysis.expected | 3 + .../nullify/query.esql | 2 + .../load/query.esql | 2 + .../testMultipleEval/load/analysis.expected | 5 + .../testMultipleEval/load/query.esql | 4 + .../nullify/analysis.expected | 5 + .../testMultipleEval/nullify/query.esql | 4 + .../testMvExpand/load/analysis.expected | 3 + .../testMvExpand/load/query.esql | 2 + .../testMvExpand/nullify/analysis.expected | 4 + .../testMvExpand/nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../testPartiallyMappedField/load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../testRename/load/analysis.expected | 3 + .../testRename/load/query.esql | 2 + .../testRename/nullify/analysis.expected | 4 + .../testRename/nullify/query.esql | 2 + .../testRenameEval/load/analysis.expected | 4 + .../testRenameEval/load/query.esql | 3 + .../testRenameEval/nullify/analysis.expected | 5 + .../testRenameEval/nullify/query.esql | 3 + .../testRenameRepeated/load/analysis.expected | 3 + .../testRenameRepeated/load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../testRenameRepeated/nullify/query.esql | 2 + .../testSort/load/analysis.expected | 3 + .../testSort/load/query.esql | 2 + .../testSort/nullify/analysis.expected | 4 + .../testSort/nullify/query.esql | 2 + .../testSortExpression/load/analysis.expected | 3 + .../testSortExpression/load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../testSortExpression/nullify/query.esql | 2 + .../testSortMultiple/load/analysis.expected | 3 + .../testSortMultiple/load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../testSortMultiple/nullify/query.esql | 2 + .../testStatsBy/load/analysis.expected | 3 + .../testStatsBy/load/query.esql | 2 + .../testStatsBy/nullify/analysis.expected | 4 + .../testStatsBy/nullify/query.esql | 2 + .../testStatsCount/load/analysis.expected | 3 + .../testStatsCount/load/query.esql | 2 + .../testStatsCount/nullify/analysis.expected | 4 + .../testStatsCount/nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../testStatsCountWhere/load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../testStatsCountWhere/nullify/query.esql | 2 + .../testStatsMultiple/load/analysis.expected | 3 + .../testStatsMultiple/load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../testStatsMultiple/nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../load/query.esql | 3 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 3 + .../testStatsSumBy/load/analysis.expected | 3 + .../testStatsSumBy/load/query.esql | 2 + .../testStatsSumBy/nullify/analysis.expected | 4 + .../testStatsSumBy/nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../testStatsSumByComplex/load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../testStatsSumByComplex/nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../testStatsSumByMultiple/load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../testStatsSumByMultiple/nullify/query.esql | 2 + .../load/analysis.expected | 11 + .../load/query.esql | 3 + .../nullify/analysis.expected | 12 + .../nullify/query.esql | 3 + .../load/analysis.expected | 13 + .../testSubqueryKeepUnmapped/load/query.esql | 2 + .../nullify/analysis.expected | 14 + .../nullify/query.esql | 2 + .../load/analysis.expected | 11 + .../testSubqueryWithStats/load/query.esql | 2 + .../nullify/analysis.expected | 12 + .../testSubqueryWithStats/nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../load/analysis.expected | 3 + .../load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../nullify/analysis.expected | 4 + .../nullify/query.esql | 2 + .../testWhere/load/analysis.expected | 3 + .../testWhere/load/query.esql | 2 + .../testWhere/nullify/analysis.expected | 4 + .../testWhere/nullify/query.esql | 2 + .../testWhereComplex/load/analysis.expected | 3 + .../testWhereComplex/load/query.esql | 2 + .../nullify/analysis.expected | 4 + .../testWhereComplex/nullify/query.esql | 2 + .../testWhereOr/load/analysis.expected | 3 + .../testWhereOr/load/query.esql | 2 + .../testWhereOr/nullify/analysis.expected | 4 + .../testWhereOr/nullify/query.esql | 2 + .../load/local_physical_optimization.expected | 6 +- .../local_physical_optimization.expected | 2 +- .../load/local_physical_optimization.expected | 6 +- .../local_physical_optimization.expected | 6 +- .../load/local_physical_optimization.expected | 6 +- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 6 +- .../local_physical_optimization.expected | 6 +- .../load/local_physical_optimization.expected | 10 +- .../local_physical_optimization.expected | 8 +- .../load/local_physical_optimization.expected | 10 +- .../local_physical_optimization.expected | 6 +- .../local_physical_optimization.expected | 8 +- .../local_physical_optimization.expected | 12 +- .../local_physical_optimization.expected | 12 +- .../local_physical_optimization.expected | 12 +- .../local_physical_optimization.expected | 4 +- .../local_physical_optimization.expected | 4 +- .../local_physical_optimization.expected | 4 +- .../local_physical_optimization.expected | 6 +- .../local_physical_optimization.expected | 6 +- .../local_physical_optimization.expected | 6 +- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 2 +- .../local_physical_optimization.expected | 10 +- .../local_physical_optimization.expected | 10 +- .../local_physical_optimization.expected | 12 +- .../local_physical_optimization.expected | 4 +- ...physical_optimization_data_driver.expected | 4 +- .../local_reduce_planned_data_driver.expected | 6 +- ...ocal_reduce_planned_reduce_driver.expected | 8 +- .../physical_optimization.expected | 10 +- ...physical_optimization_data_driver.expected | 4 +- .../local_reduce_planned_data_driver.expected | 4 +- ...ocal_reduce_planned_reduce_driver.expected | 6 +- .../physical_optimization.expected | 6 +- ...physical_optimization_data_driver.expected | 4 +- .../local_reduce_planned_data_driver.expected | 4 +- ...ocal_reduce_planned_reduce_driver.expected | 6 +- .../physical_optimization.expected | 6 +- ...physical_optimization_data_driver.expected | 10 +- .../local_reduce_planned_data_driver.expected | 10 +- ...ocal_reduce_planned_reduce_driver.expected | 8 +- .../physical_optimization.expected | 12 +- ...physical_optimization_data_driver.expected | 4 +- .../local_reduce_planned_data_driver.expected | 6 +- ...ocal_reduce_planned_reduce_driver.expected | 8 +- .../physical_optimization.expected | 10 +- ...physical_optimization_data_driver.expected | 4 +- .../local_reduce_planned_data_driver.expected | 6 +- ...ocal_reduce_planned_reduce_driver.expected | 8 +- .../physical_optimization.expected | 12 +- ...physical_optimization_data_driver.expected | 10 +- ...ysical_optimization_reduce_driver.expected | 6 +- .../local_reduce_planned_data_driver.expected | 10 +- ...ocal_reduce_planned_reduce_driver.expected | 6 +- .../physical_optimization.expected | 12 +- ...physical_optimization_data_driver.expected | 4 +- .../local_reduce_planned_data_driver.expected | 6 +- ...ocal_reduce_planned_reduce_driver.expected | 8 +- .../physical_optimization.expected | 10 +- ...physical_optimization_data_driver.expected | 4 +- .../local_reduce_planned_data_driver.expected | 6 +- ...ocal_reduce_planned_reduce_driver.expected | 8 +- .../physical_optimization.expected | 10 +- ...physical_optimization_data_driver.expected | 4 +- .../local_reduce_planned_data_driver.expected | 6 +- ...ocal_reduce_planned_reduce_driver.expected | 8 +- .../physical_optimization.expected | 10 +- ...physical_optimization_data_driver.expected | 4 +- .../local_reduce_planned_data_driver.expected | 6 +- ...ocal_reduce_planned_reduce_driver.expected | 8 +- .../physical_optimization.expected | 10 +- .../sql/qa/server/src/main/resources/apps.csv | 2 +- 315 files changed, 1882 insertions(+), 281 deletions(-) create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/query.esql diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/data/all-types.csv b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/data/all-types.csv index b6447d688c9d1..cdb40caa14a81 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/data/all-types.csv +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/data/all-types.csv @@ -1 +1,6 @@ -alias_integer,boolean,byte,constant_keyword-foo,date,date_nanos,double,float,half_float,scaled_float,integer,ip,keyword,long,unsigned_long,short,text,version,wildcard,semantic_text,dense_vector +boolean:boolean,byte:byte,constant_keyword-foo:keyword,date:date,date_nanos:date_nanos,double:double,float:float,half_float:half_float,scaled_float:scaled_float,integer:integer,ip:ip,keyword:keyword,long:long,unsigned_long:unsigned_long,short:short,text:text,version:version,wildcard:keyword +true,1,foo,2024-01-01T00:00:00.000Z,2024-01-01T00:00:00.000000001Z,1.1,1.1,1.1,1.1,1,127.0.0.1,key1,100,100,10,text1,1.0.0,wild1 +false,2,foo,2024-01-02T00:00:00.000Z,2024-01-02T00:00:00.000000002Z,2.2,2.2,2.2,2.2,2,127.0.0.2,key2,200,200,20,text2,2.0.0,wild2 +true,3,foo,2024-01-03T00:00:00.000Z,2024-01-03T00:00:00.000000003Z,3.3,3.3,3.3,3.3,3,127.0.0.3,key3,300,300,30,text3,3.0.0,wild3 +false,4,foo,2024-01-04T00:00:00.000Z,2024-01-04T00:00:00.000000004Z,4.4,4.4,4.4,4.4,4,127.0.0.4,key4,400,400,40,text4,4.0.0,wild4 +true,5,foo,2024-01-05T00:00:00.000Z,2024-01-05T00:00:00.000000005Z,5.5,5.5,5.5,5.5,5,127.0.0.5,key5,500,500,50,text5,5.0.0,wild5 diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec index 4466350f617ca..a70d9a79e7561 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec @@ -12,6 +12,22 @@ null null ; +partialMappingUnmappedFromSource +required_capability: optional_fields_nullify_tech_preview + +SET unmapped_fields="nullify"\; +FROM partial_mapping_sample_data +| KEEP @timestamp, unmapped_message +| SORT @timestamp DESC +| LIMIT 3 +; + +@timestamp:date | unmapped_message:null +2024-10-23T13:55:01.543Z | null +2024-10-23T13:53:55.832Z | null +2024-10-23T13:52:55.015Z | null +; + keepStar required_capability: optional_fields_nullify_tech_preview @@ -482,3 +498,93 @@ ROW x = 1 x:integer |does_not_exist:null |y:keyword | language_name:keyword 1 |null |null |null ; + +partiallyUnmappedKeywordMultiIndex +required_capability: optional_fields_nullify_tech_preview +required_capability: index_metadata_field + +SET unmapped_fields="nullify"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| KEEP _index, @timestamp, message +| SORT _index, @timestamp DESC +; + +_index:keyword | @timestamp:date | message:keyword +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +sample_data | 2023-10-23T13:55:01.543Z | Connected to 10.1.0.1 +sample_data | 2023-10-23T13:53:55.832Z | Connection error +sample_data | 2023-10-23T13:52:55.015Z | Connection error +sample_data | 2023-10-23T13:51:54.732Z | Connection error +sample_data | 2023-10-23T13:33:34.937Z | Disconnected +sample_data | 2023-10-23T12:27:28.948Z | Connected to 10.1.0.2 +sample_data | 2023-10-23T12:15:03.360Z | Connected to 10.1.0.3 +; + +partiallyUnmappedNonKeywordMultiIndexCast +required_capability: optional_fields_nullify_tech_preview +required_capability: index_metadata_field + +SET unmapped_fields="nullify"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL duration = event_duration::DOUBLE +| KEEP _index, @timestamp, duration +| SORT _index, @timestamp DESC +; + +_index:keyword | @timestamp:date | duration:double +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +sample_data | 2023-10-23T13:55:01.543Z | 1756467.0 +sample_data | 2023-10-23T13:53:55.832Z | 5033755.0 +sample_data | 2023-10-23T13:52:55.015Z | 8268153.0 +sample_data | 2023-10-23T13:51:54.732Z | 725448.0 +sample_data | 2023-10-23T13:33:34.937Z | 1232382.0 +sample_data | 2023-10-23T12:27:28.948Z | 2764889.0 +sample_data | 2023-10-23T12:15:03.360Z | 3450233.0 +; + +partiallyUnmappedMixedTypesMultiIndexCast +required_capability: optional_fields_nullify_tech_preview +required_capability: index_metadata_field + +SET unmapped_fields="nullify"\; +FROM sample_data, logs, no_mapping_sample_data METADATA _index +| EVAL msg = message::KEYWORD +| KEEP _index, @timestamp, msg +| SORT _index, @timestamp DESC +; + +_index:keyword | @timestamp:date | msg:keyword +logs | 2023-10-23T13:57:01.544Z | Running cats (cycle 3) +logs | 2023-10-23T13:56:01.544Z | Running cats (cycle 2) +logs | 2023-10-23T13:56:01.543Z | No response +logs | 2023-10-23T13:55:01.546Z | More java stuff +logs | 2023-10-23T13:55:01.545Z | Doing java stuff for 192.168.86.038 +logs | 2023-10-23T13:55:01.544Z | Running cats (cycle 1) +logs | 2023-10-23T13:55:01.543Z | Pinging 192.168.86.046 +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +no_mapping_sample_data | null | null +sample_data | 2023-10-23T13:55:01.543Z | Connected to 10.1.0.1 +sample_data | 2023-10-23T13:53:55.832Z | Connection error +sample_data | 2023-10-23T13:52:55.015Z | Connection error +sample_data | 2023-10-23T13:51:54.732Z | Connection error +sample_data | 2023-10-23T13:33:34.937Z | Disconnected +sample_data | 2023-10-23T12:27:28.948Z | Connected to 10.1.0.2 +sample_data | 2023-10-23T12:15:03.360Z | Connected to 10.1.0.3 +; 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 df7d8d59e01bc..390a1ebac7d60 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 @@ -856,6 +856,11 @@ public enum Cap { */ SOURCE_FIELD_MAPPING, + /** + * Support for field aliases in mappings. + */ + FIELD_ALIAS_SUPPORT, + /** * Allow filter per individual aggregation. */ diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Alias.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Alias.java index 348374f7b174e..6e8b20f5a05a7 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Alias.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Alias.java @@ -143,7 +143,7 @@ public String toString() { @Override public String nodeString(NodeStringFormat format) { - return child.nodeString() + " AS " + name() + "#" + id(); + return child.nodeString(format) + " AS " + name() + "#" + id(); } /** diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Attribute.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Attribute.java index 69233e86ef865..62cfd9786b0c7 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Attribute.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/Attribute.java @@ -221,7 +221,7 @@ public String toString() { @Override public String nodeString(NodeStringFormat format) { - return toString(); + return toString(format); } protected abstract String label(); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/FieldAttribute.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/FieldAttribute.java index bd6377cfd109d..14e1e9c6c094d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/FieldAttribute.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/expression/FieldAttribute.java @@ -271,4 +271,14 @@ public boolean isMetric() { public EsField field() { return field; } + + @Override + public String nodeString(NodeStringFormat format) { + return switch (format) { + case FULL -> Strings.format( + "%s{%s(%s)%s}#%s".formatted(qualifiedName(), label(), field.getWriteableName(), synthetic() ? "$" : "", id()) + ); + case LIMITED -> super.nodeString(format); + }; + } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java index d02fb6b92ccf4..ac5d09b1dcec4 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java @@ -732,7 +732,8 @@ public static Map testDa private static TestPhysicalOperationProviders testOperationProviders( FoldContext foldCtx, - Map allDatasets + Map allDatasets, + UnmappedResolution unmappedResolution ) throws Exception { var indexPages = new ArrayList(); for (CsvTestsDataLoader.MultiIndexTestDataset datasets : allDatasets.values()) { @@ -744,7 +745,7 @@ private static TestPhysicalOperationProviders testOperationProviders( ); } } - return TestPhysicalOperationProviders.create(foldCtx, indexPages); + return TestPhysicalOperationProviders.create(foldCtx, indexPages, unmappedResolution); } private ActualResults executePlan(BigArrays bigArrays) throws Exception { @@ -760,7 +761,8 @@ private ActualResults executePlan(BigArrays bigArrays) throws Exception { var testDatasets = testDatasets(plan); // Specifically use the newest transport version; the csv tests correspond to a single node cluster on the current version. TransportVersion minimumVersion = TransportVersion.current(); - LogicalPlan analyzed = analyzedPlan(plan, statement.setting(UNMAPPED_FIELDS), configuration, testDatasets, minimumVersion); + var unmappedResolution = statement.setting(UNMAPPED_FIELDS); + LogicalPlan analyzed = analyzedPlan(plan, unmappedResolution, configuration, testDatasets, minimumVersion); FoldContext foldCtx = FoldContext.small(); EsqlSession session = new EsqlSession( @@ -782,7 +784,7 @@ private ActualResults executePlan(BigArrays bigArrays) throws Exception { PlannerSettings.DEFAULTS, EsqlTestUtils.MOCK_TRANSPORT_ACTION_SERVICES ); - TestPhysicalOperationProviders physicalOperationProviders = testOperationProviders(foldCtx, testDatasets); + TestPhysicalOperationProviders physicalOperationProviders = testOperationProviders(foldCtx, testDatasets, unmappedResolution); PlainActionFuture listener = new PlainActionFuture<>(); var logicalPlanPreOptimizer = new LogicalPlanPreOptimizer( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java new file mode 100644 index 0000000000000..493bbc4d70d63 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -0,0 +1,491 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.analysis; + +import org.elasticsearch.xpack.esql.action.EsqlCapabilities; +import org.elasticsearch.xpack.esql.optimizer.GoldenTestCase; + +import java.util.EnumSet; +import java.util.Optional; + +/** + * Golden tests for analyzer behavior with unmapped fields using SET unmapped_fields="nullify" and "load". + * These tests verify that unmapped fields are properly handled. + */ +public class AnalyzerUnmappedGoldenTests extends GoldenTestCase { + private static final EnumSet STAGES = EnumSet.of(Stage.ANALYSIS); + + public void testKeep() throws Exception { + runTests(""" + FROM employees + | eval x = does_not_exist_field :: version + | keep x + """); + } + + public void testKeepRepeated() throws Exception { + runTests(""" + FROM employees + | KEEP does_not_exist_field, does_not_exist_field + """); + } + + public void testKeepAndMatchingStar() throws Exception { + runTests(""" + FROM employees + | KEEP emp_*, does_not_exist_field + """); + } + + public void testEvalAndKeep() throws Exception { + runTests(""" + FROM employees + | EVAL x = does_not_exist_field1::INTEGER + 42 + | KEEP does_not_exist_field1, does_not_exist_field2 + """); + } + + public void testEvalAfterKeepStar() throws Exception { + runTests(""" + FROM employees + | KEEP * + | EVAL x = emp_no + 1 + | EVAL y = does_not_exist_field::DOUBLE + 2 + """); + } + + public void testEvalAfterMatchingKeepWithWildcard() throws Exception { + runTests(""" + FROM employees + | KEEP emp_no, * + | EVAL x = emp_no + 1 + | EVAL y = emp_does_not_exist_field::DOUBLE + 2 + """); + } + + public void testDrop() throws Exception { + runTests(""" + FROM employees + | DROP does_not_exist_field, emp_no + """); + } + + public void testDropAndMatchingStar() throws Exception { + runTests(""" + FROM employees + | DROP emp_*, does_not_exist_field + """); + } + + public void testRename() throws Exception { + runTests(""" + FROM employees + | RENAME does_not_exist_field AS now_it_does, emp_no AS employee_number + """); + } + + public void testRenameRepeated() throws Exception { + runTests(""" + FROM employees + | RENAME does_not_exist_field AS now_it_does, neither_does_this AS now_it_does, emp_no AS employee_number + """); + } + + public void testRenameEval() throws Exception { + runTests(""" + FROM employees + | RENAME emp_no AS employee_number + | EVAL x = does_not_exist::DOUBLE + 1 + """); + } + + public void testEval() throws Exception { + runTests(""" + FROM employees + | EVAL x = does_not_exist_field::DOUBLE + 1 + """); + } + + public void testMultipleEval() throws Exception { + runTests(""" + FROM employees + | EVAL a = 1 + | EVAL x = a + b::DOUBLE + | EVAL y = b::DOUBLE + c::DOUBLE + """); + } + + public void testEvalCast() throws Exception { + runTests(""" + FROM employees + | EVAL x = does_not_exist_field::LONG + """); + } + + public void testEvalCastInPlace() throws Exception { + runTests(""" + FROM employees + | EVAL does_not_exist_field::LONG + """); + } + + public void testEvalReplace() throws Exception { + runTests(""" + FROM employees + | EVAL x = does_not_exist_field::DOUBLE + 1 + | EVAL does_not_exist_field = 42 + """); + } + + public void testKeepThenEval() throws Exception { + runTests(""" + FROM employees + | KEEP does_not_exist_field + | EVAL does_not_exist_field = 42 + """); + } + + public void testStatsCount() throws Exception { + runTests(""" + FROM employees + | STATS cnt = COUNT(does_not_exist_field) + """); + } + + public void testStatsBy() throws Exception { + runTests(""" + FROM employees + | STATS BY does_not_exist_field + """); + } + + public void testDoesNotExistAfterInlineStats() throws Exception { + runTests(""" + FROM employees + | INLINE STATS COUNT(*) BY emp_no + | EVAL x = does_not_exist_field + """); + } + + public void testStatsSumBy() throws Exception { + runTests(""" + FROM employees + | STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 + """); + } + + public void testStatsSumByMultiple() throws Exception { + runTests(""" + FROM employees + | STATS s = SUM(does_not_exist1::DOUBLE) + d2 BY d2 = does_not_exist2::DOUBLE, emp_no + """); + } + + public void testStatsSumByComplex() throws Exception { + runTests(""" + FROM employees + | STATS sum = SUM(does_not_exist1::DOUBLE) + s0 + s1 BY s0 = does_not_exist2::DOUBLE + does_not_exist3::DOUBLE, s1 = emp_no + """); + } + + public void testStatsMultiple() throws Exception { + runTests(""" + FROM employees + | STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no + """); + } + + public void testInlineStats() throws Exception { + runTests(""" + FROM employees + | INLINE STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no + """); + } + + public void testWhere() throws Exception { + runTests(""" + FROM employees + | WHERE does_not_exist::LONG > 0 + """); + } + + public void testWhereOr() throws Exception { + runTests(""" + FROM employees + | WHERE does_not_exist::LONG > 0 OR emp_no > 0 + """); + } + + public void testWhereComplex() throws Exception { + runTests(""" + FROM employees + | WHERE does_not_exist1::LONG > 0 OR emp_no > 0 AND does_not_exist2::LONG < 100 + """); + } + + public void testStatsCountWhere() throws Exception { + runTests(""" + FROM employees + | STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 + """); + } + + public void testStatsMultipleCountWhere() throws Exception { + runTests(""" + FROM employees + | STATS c1 = COUNT(*) WHERE does_not_exist1::LONG > 0 OR emp_no > 0 OR does_not_exist2::LONG < 100, + c2 = COUNT(*) WHERE does_not_exist3 IS NULL + """); + } + + public void testSort() throws Exception { + runTests(""" + FROM employees + | SORT does_not_exist ASC + """); + } + + public void testSortExpression() throws Exception { + runTests(""" + FROM employees + | SORT does_not_exist::LONG + 1 + """); + } + + public void testSortMultiple() throws Exception { + runTests(""" + FROM employees + | SORT does_not_exist1::LONG + 1, does_not_exist2 DESC, emp_no ASC + """); + } + + public void testMvExpand() throws Exception { + runTests(""" + FROM employees + | MV_EXPAND does_not_exist + """); + } + + public void testLookupJoin() throws Exception { + runTests(""" + FROM employees + | EVAL language_code = does_not_exist :: INTEGER + | LOOKUP JOIN languages_lookup ON language_code + """); + } + + public void testLookupJoinWithFilter() throws Exception { + runTests(""" + FROM employees + | EVAL language_code = languages + | LOOKUP JOIN languages_lookup ON language_code + | WHERE does_not_exist::LONG > 0 + """); + } + + public void testSubqueryKeepUnmapped() throws Exception { + runTests(""" + FROM employees, (FROM languages | KEEP language_code) + | KEEP emp_no, language_code, does_not_exist + """); + } + + public void testSubqueryWithStats() throws Exception { + runTests(""" + FROM employees, (FROM sample_data | STATS max_ts = MAX(@timestamp) BY does_not_exist) + | KEEP emp_no, max_ts, does_not_exist + """); + } + + public void testSubqueryKeepMultipleUnmapped() throws Exception { + runTests(""" + FROM employees, + (FROM languages | KEEP language_code, unmapped1, unmapped2) + | KEEP emp_no, language_code, unmapped1, unmapped2 + """); + } + + public void testFork() throws Exception { + runTests(""" + FROM employees + | FORK (WHERE does_not_exist::LONG > 0) + (WHERE emp_no > 0) + """); + } + + public void testForkWithEval() throws Exception { + runTests(""" + FROM employees + | FORK (EVAL x = does_not_exist::DOUBLE + 1) + (EVAL y = emp_no + 1) + """); + } + + public void testForkWithStats() throws Exception { + runTests(""" + FROM employees + | FORK (STATS c = COUNT(*) BY does_not_exist) + (STATS d = AVG(salary::DOUBLE)) + | SORT does_not_exist + """); + } + + public void testFuse() throws Exception { + assumeTrue("requires FUSE capability", EsqlCapabilities.Cap.FUSE_V6.isEnabled()); + runTests(""" + FROM employees METADATA _score, _index, _id + | FORK (WHERE does_not_exist::LONG > 0) + (WHERE emp_no > 0) + | FUSE + """); + } + + public void testFuseWithEval() throws Exception { + assumeTrue("requires FUSE capability", EsqlCapabilities.Cap.FUSE_V6.isEnabled()); + runTests(""" + FROM employees METADATA _score, _index, _id + | FORK (EVAL x = does_not_exist::DOUBLE + 1) + (EVAL y = emp_no + 1) + | FUSE RRF + """); + } + + public void testFuseLinear() throws Exception { + assumeTrue("requires FUSE capability", EsqlCapabilities.Cap.FUSE_V6.isEnabled()); + runTests(""" + FROM employees METADATA _score, _index, _id + | FORK (WHERE does_not_exist::LONG > 0 | EVAL x = 1) + (WHERE emp_no > 0 | EVAL y = 2) + | FUSE LINEAR + """); + } + + public void testCoalesce() throws Exception { + runTests(""" + FROM employees + | EVAL x = COALESCE(does_not_exist::LONG, emp_no, 0) + | KEEP emp_no, x + """); + } + + public void testTBucketGroupByUnmapped() throws Exception { + runTests(""" + FROM sample_data + | STATS c = COUNT(*) BY tbucket(1 hour), does_not_exist + """); + } + + public void testTBucketAggregateUnmapped() throws Exception { + runTests(""" + FROM sample_data + | STATS s = SUM(does_not_exist::DOUBLE), c = COUNT(*) BY tbucket(1 day) + """); + } + + public void testTimeSeriesRateUnmapped() throws Exception { + runTestsNullifyOnly(""" + TS k8s + | STATS r = RATE(does_not_exist) BY tbucket(1 hour) + """); + } + + public void testTimeSeriesFirstOverTimeUnmapped() throws Exception { + runTests(""" + TS k8s + | STATS f = FIRST_OVER_TIME(does_not_exist::DOUBLE) BY tbucket(1 hour) + """); + } + + public void testPartiallyMappedField() throws Exception { + runTests(""" + FROM sample_data, partial_mapping_sample_data + | KEEP @timestamp, message, unmapped_message + """); + } + + public void testMappedInOneIndexOnly() throws Exception { + runTests(""" + FROM sample_data, no_mapping_sample_data + | KEEP message + """); + } + + public void testMappedInOneIndexOnlyCast() throws Exception { + runTests(""" + FROM sample_data, no_mapping_sample_data + | EVAL x = message :: LONG + """); + } + + public void testMappedToNonKeywordInOneIndexOnly() throws Exception { + runTests(""" + FROM sample_data, no_mapping_sample_data + | KEEP event_duration + """); + } + + public void testDifferentTypesAndUnmapped() throws Exception { + runTests(""" + FROM sample_data, sample_data_ts_long, no_mapping_sample_data + | KEEP @timestamp + """); + } + + public void testDifferentTypesAndUnmappedCast() throws Exception { + runTests(""" + FROM sample_data, sample_data_ts_long, no_mapping_sample_data + | EVAL x = @timestamp :: DOUBLE + """); + } + + private static String setUnmappedNullify(String query) { + return "SET unmapped_fields=\"nullify\"; " + query; + } + + private static String setUnmappedLoad(String query) { + return "SET unmapped_fields=\"load\"; " + query; + } + + private void runTests(String query) { + var nullifyException = tryRunTestsNullifyOnly(query); + var loadException = tryRunTestsLoadOnly(query); + if (nullifyException.isPresent() && loadException.isPresent()) { + throw new AssertionError("Both nullify and load modes failed", nullifyException.get()); + } else if (nullifyException.isPresent()) { + throw new AssertionError("Nullify mode failed (but load succeeded)", nullifyException.get()); + } else if (loadException.isPresent()) { + throw new AssertionError("Load mode failed (but nullify succeeded)", loadException.get()); + } + } + + private void runTestsNullifyOnly(String query) { + var nullifyException = tryRunTestsNullifyOnly(query); + if (nullifyException.isPresent()) { + throw new RuntimeException("Nullify mode failed", nullifyException.get()); + } + } + + private Optional tryRunTestsNullifyOnly(String query) { + return EsqlCapabilities.Cap.OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW.isEnabled() + ? builder(setUnmappedNullify(query)).nestedPath("nullify").stages(STAGES).tryRun() + : Optional.empty(); + } + + private void runTestsLoadOnly(String query) { + var loadException = tryRunTestsLoadOnly(query); + if (loadException.isPresent()) { + throw new RuntimeException("Load mode failed", loadException.get()); + } + } + + private Optional tryRunTestsLoadOnly(String query) { + return EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled() + ? builder(setUnmappedLoad(query)).nestedPath("load").stages(STAGES).tryRun() + : Optional.empty(); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index d7b0cc348d227..18704cc4a981b 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -914,6 +914,17 @@ public void testFailStatsThenEval() { verificationFailure(setUnmappedLoad(query), failure); } + public void testFailStatsThenEvalExistingField() { + var query = """ + FROM test + | STATS cnt = COUNT(*) + | EVAL x = emp_no + """; + var failure = "line 3:12: Unknown column [emp_no]"; + verificationFailure(setUnmappedNullify(query), failure); + verificationFailure(setUnmappedLoad(query), failure); + } + /* * Limit[1000[INTEGER],false,false] * \_Aggregate[[],[COUNT(does_not_exist_field{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt#5]] @@ -3195,6 +3206,17 @@ public void testLookupJoin() { assertThat(rightRel.indexPattern(), is("languages_lookup")); } + public void testFailLookupJoinWithoutCast() { + String query = """ + FROM test + | EVAL language_code = does_not_exist + | LOOKUP JOIN languages_lookup ON language_code + """; + var failure = "is incompatible with right field [language_code] of type [INTEGER]"; + verificationFailure(setUnmappedNullify(query), failure); + verificationFailure(setUnmappedLoad(query), failure); + } + /* * Limit[1000[INTEGER],false,false] * \_Enrich[ANY,languages[KEYWORD],x{r}#5,{"match":{"indices":[],"match_field":"language_code", @@ -3270,6 +3292,26 @@ public void testSemanticText() { assertThat(relation.indexPattern(), is("test")); } + public void testFailSemanticTextLoad() { + String query = """ + FROM test + | WHERE KNN(does_not_exist, [0, 1, 2]) + """; + var failure = "first argument of [KNN(does_not_exist, [0, 1, 2])] must be [dense_vector, null, text], " + + "found value [does_not_exist] type [keyword]"; + verificationFailure(setUnmappedLoad(query), failure); + } + + public void testFailRateLoad() { + String query = """ + TS k8s + | STATS max(rate(does_not_exist)) + """; + var failure = "first argument of [rate(does_not_exist)] must be [counter_long, counter_integer or counter_double], " + + "found value [does_not_exist] type [keyword]"; + verificationFailure(setUnmappedLoad(query), failure); + } + /* * Limit[1000[INTEGER],false,false] * \_Project[[x{r}#4, does_not_exist_field1{r}#12, y{r}#8, does_not_exist_field2{r}#14]] @@ -3454,6 +3496,17 @@ public void testChangedTimestmapFieldWithRate() { """), "3:13: [rate(network.total_cost)] " + UnresolvedTimestamp.UNRESOLVED_SUFFIX); } + // This test verifies that we do not allow an unmapped @timestamp fields in tbucket. + public void testFailNoUnmappedTimestamp() throws Exception { + String query = (""" + FROM employees + | STATS c = COUNT(*) BY tbucket(1 hour) + """); + var failure = "[tbucket(1 hour)] requires the [@timestamp] field"; + verificationFailure(setUnmappedNullify(query), failure); + verificationFailure(setUnmappedLoad(query), failure); + } + private void verificationFailure(String statement, String expectedFailure) { var e = expectThrows(VerificationException.class, () -> analyzeStatement(statement)); assertThat(e.getMessage(), containsString(expectedFailure)); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index 1bfb7e7a301ae..cb522973326ef 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -57,6 +57,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Optional; import java.util.EnumSet; import java.util.HashMap; import java.util.List; @@ -177,6 +178,15 @@ public TestBuilder transportVersion(TransportVersion transportVersion) { public void run() { runGoldenTest(esqlQuery, stages, searchStats, transportVersion, nestedPath); } + + public Optional tryRun() { + try { + run(); + return Optional.empty(); + } catch (Throwable e) { + return Optional.of(e); + } + } } private record Test( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java index 8f9ac14c1c80d..4808aa5a391da 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java @@ -43,6 +43,7 @@ import org.elasticsearch.plugins.scanners.StablePluginsRegistry; import org.elasticsearch.xpack.cluster.routing.allocation.mapper.DataTierFieldMapper; import org.elasticsearch.xpack.esql.EsqlIllegalArgumentException; +import org.elasticsearch.xpack.esql.analysis.UnmappedResolution; import org.elasticsearch.xpack.esql.core.expression.Attribute; import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; import org.elasticsearch.xpack.esql.core.expression.FoldContext; @@ -77,14 +78,25 @@ public class TestPhysicalOperationProviders extends AbstractPhysicalOperationProviders { private final List indexPages; + private final UnmappedResolution unmappedResolution; - private TestPhysicalOperationProviders(FoldContext foldContext, List indexPages, AnalysisRegistry analysisRegistry) { + private TestPhysicalOperationProviders( + FoldContext foldContext, + List indexPages, + UnmappedResolution unmappedResolution, + AnalysisRegistry analysisRegistry + ) { super(foldContext, analysisRegistry); this.indexPages = indexPages; + this.unmappedResolution = unmappedResolution; } - public static TestPhysicalOperationProviders create(FoldContext foldContext, List indexPages) throws IOException { - return new TestPhysicalOperationProviders(foldContext, indexPages, createAnalysisRegistry()); + public static TestPhysicalOperationProviders create( + FoldContext foldContext, + List indexPages, + UnmappedResolution unmappedResolution + ) throws IOException { + return new TestPhysicalOperationProviders(foldContext, indexPages, unmappedResolution, createAnalysisRegistry()); } public record IndexPage(String index, Page page, List columnNames, Set mappedFields) { @@ -92,6 +104,7 @@ Optional columnIndex(String columnName) { var result = IntStream.range(0, columnNames.size()).filter(i -> columnNames.get(i).equals(columnName)).findFirst(); return result.isPresent() ? Optional.of(result.getAsInt()) : Optional.empty(); } + } private static AnalysisRegistry createAnalysisRegistry() throws IOException { @@ -292,11 +305,12 @@ private BiFunction getBlockExtraction(DriverCo } } return (indexDoc, blockCopier) -> switch (extractBlockForSingleDoc(indexDoc, attribute.name(), blockCopier)) { - case BlockResultMissing missing -> throw new EsqlIllegalArgumentException( - "Cannot find column named [{}] in {}", - missing.columnName, - missing.columnNames - ); + case BlockResultMissing missing -> { + if (unmappedResolution == UnmappedResolution.NULLIFY) { + yield getNullsBlock(indexDoc); + } + throw new EsqlIllegalArgumentException("Cannot find column named [{}] in {}", missing.columnName, missing.columnNames); + } case BlockResultSuccess success -> success.block; }; } @@ -347,9 +361,11 @@ private BlockResult extractBlockForSingleDoc(DocBlock docBlock, String columnNam docBlock.blockFactory() .newConstantBytesRefBlockWith(new BytesRef("data_content"), blockCopier.docIndices.getPositionCount()) ); - default -> indexPage.columnIndex(columnName) - .map(columnIndex -> new BlockResultSuccess(blockCopier.copyBlock(indexPage.page.getBlock(columnIndex)))) - .orElseGet(() -> new BlockResultMissing(columnName, indexPage.columnNames())); + default -> unmappedResolution == UnmappedResolution.NULLIFY && indexPage.mappedFields().contains(columnName) == false + ? new BlockResultMissing(columnName, indexPage.columnNames()) + : indexPage.columnIndex(columnName) + .map(columnIndex -> new BlockResultSuccess(blockCopier.copyBlock(indexPage.page.getBlock(columnIndex)))) + .orElseGet(() -> new BlockResultMissing(columnName, indexPage.columnNames())); }; } diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/analysis.expected new file mode 100644 index 0000000000000..e3749cf60fe6d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{f(EsField)}#0, x{r}#1]] + \_Eval[[COALESCE(TOLONG(does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2),TOLONG(emp_no{f(EsField)}#0),TOLONG(0[INTEGER])) AS x#1]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#0, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist{f}#2, x{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/query.esql new file mode 100644 index 0000000000000..fffcba043eaeb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| EVAL x = COALESCE(does_not_exist::LONG, emp_no, 0) +| KEEP emp_no, x diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/analysis.expected new file mode 100644 index 0000000000000..bcdfea953020a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{f(EsField)}#0, x{r}#1]] + \_Eval[[COALESCE(TOLONG(does_not_exist{r}#2),TOLONG(emp_no{f(EsField)}#0),TOLONG(0[INTEGER])) AS x#1]] + \_Eval[[null[NULL] AS does_not_exist#2, null[NULL] AS x#3]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/query.esql new file mode 100644 index 0000000000000..7de1ffe56d169 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testCoalesce/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL x = COALESCE(does_not_exist::LONG, emp_no, 0) +| KEEP emp_no, x diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..338fc3701e44c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[!@timestamp]] + \_EsRelation[sample_data,sample_data_ts_long,no_mapping_sample_data][!@timestamp, client_ip{f}#0, event_duration{f}#1, message{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/query.esql new file mode 100644 index 0000000000000..1e55cfb1096c9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, sample_data_ts_long, no_mapping_sample_data +| KEEP @timestamp diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..338fc3701e44c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[!@timestamp]] + \_EsRelation[sample_data,sample_data_ts_long,no_mapping_sample_data][!@timestamp, client_ip{f}#0, event_duration{f}#1, message{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..75305542ab2b0 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, sample_data_ts_long, no_mapping_sample_data +| KEEP @timestamp diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/analysis.expected new file mode 100644 index 0000000000000..1f2cf5e16ad87 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/analysis.expected @@ -0,0 +1,4 @@ +Project[[!@timestamp, client_ip{f(EsField)}#0, event_duration{f(EsField)}#1, message{f(KeywordEsField)}#2, x{r}#3]] +\_Limit[1000[INTEGER],false,false] + \_Eval[[$$@timestamp$converted_to$double{f(MultiTypeEsField)$}#4 AS x#3]] + \_EsRelation[sample_data,sample_data_ts_long,no_mapping_sample_data][!@timestamp, client_ip{f}#0, event_duration{f}#1, message{f}#2, $$@timestamp$converted_to$double{f$}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/query.esql new file mode 100644 index 0000000000000..b6749814f782a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, sample_data_ts_long, no_mapping_sample_data +| EVAL x = @timestamp :: DOUBLE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/analysis.expected new file mode 100644 index 0000000000000..1f2cf5e16ad87 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/analysis.expected @@ -0,0 +1,4 @@ +Project[[!@timestamp, client_ip{f(EsField)}#0, event_duration{f(EsField)}#1, message{f(KeywordEsField)}#2, x{r}#3]] +\_Limit[1000[INTEGER],false,false] + \_Eval[[$$@timestamp$converted_to$double{f(MultiTypeEsField)$}#4 AS x#3]] + \_EsRelation[sample_data,sample_data_ts_long,no_mapping_sample_data][!@timestamp, client_ip{f}#0, event_duration{f}#1, message{f}#2, $$@timestamp$converted_to$double{f$}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/query.esql new file mode 100644 index 0000000000000..e486841e2f785 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, sample_data_ts_long, no_mapping_sample_data +| EVAL x = @timestamp :: DOUBLE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/analysis.expected new file mode 100644 index 0000000000000..13558bfef2002 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0 AS x#1]] + \_InlineStats[] + \_Aggregate[[emp_no{f(EsField)}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS COUNT(*)#3, emp_no{f(EsField)}#2]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/query.esql new file mode 100644 index 0000000000000..4148af41e94f6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| INLINE STATS COUNT(*) BY emp_no +| EVAL x = does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/analysis.expected new file mode 100644 index 0000000000000..bbfb54572a2cb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/analysis.expected @@ -0,0 +1,6 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[does_not_exist_field{r}#0 AS x#1]] + \_InlineStats[] + \_Aggregate[[emp_no{f(EsField)}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS COUNT(*)#3, emp_no{f(EsField)}#2]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/query.esql new file mode 100644 index 0000000000000..00cb535f496f9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterInlineStats/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| INLINE STATS COUNT(*) BY emp_no +| EVAL x = does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected new file mode 100644 index 0000000000000..acd024f56f58a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, first_name{f(KeywordEsField)}#2, gender{f(KeywordEsField)}#3, height{f(EsField)}#4, height.float{f(EsField)}#5, height.half_float{f(EsField)}#6, height.scaled_float{f(EsField)}#7, hire_date{f(DateEsField)}#8, is_rehired{f(EsField)}#9, job_positions{f(KeywordEsField)}#10, languages{f(EsField)}#11, languages.byte{f(EsField)}#12, languages.long{f(EsField)}#13, languages.short{f(EsField)}#14, last_name{f(KeywordEsField)}#15, salary{f(EsField)}#16, salary_change{f(EsField)}#17, salary_change.int{f(EsField)}#18, salary_change.keyword{f(KeywordEsField)}#19, salary_change.long{f(EsField)}#20, still_hired{f(EsField)}#21]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#22, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21, does_not_exist_field{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/query.esql new file mode 100644 index 0000000000000..4651e798553a5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| DROP does_not_exist_field, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected new file mode 100644 index 0000000000000..9b31329838788 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, first_name{f(KeywordEsField)}#2, gender{f(KeywordEsField)}#3, height{f(EsField)}#4, height.float{f(EsField)}#5, height.half_float{f(EsField)}#6, height.scaled_float{f(EsField)}#7, hire_date{f(DateEsField)}#8, is_rehired{f(EsField)}#9, job_positions{f(KeywordEsField)}#10, languages{f(EsField)}#11, languages.byte{f(EsField)}#12, languages.long{f(EsField)}#13, languages.short{f(EsField)}#14, last_name{f(KeywordEsField)}#15, salary{f(EsField)}#16, salary_change{f(EsField)}#17, salary_change.int{f(EsField)}#18, salary_change.keyword{f(KeywordEsField)}#19, salary_change.long{f(EsField)}#20, still_hired{f(EsField)}#21]] + \_Eval[[null[NULL] AS does_not_exist_field#22]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#23, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/query.esql new file mode 100644 index 0000000000000..deb3bd1826afc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| DROP does_not_exist_field, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected new file mode 100644 index 0000000000000..acd024f56f58a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, first_name{f(KeywordEsField)}#2, gender{f(KeywordEsField)}#3, height{f(EsField)}#4, height.float{f(EsField)}#5, height.half_float{f(EsField)}#6, height.scaled_float{f(EsField)}#7, hire_date{f(DateEsField)}#8, is_rehired{f(EsField)}#9, job_positions{f(KeywordEsField)}#10, languages{f(EsField)}#11, languages.byte{f(EsField)}#12, languages.long{f(EsField)}#13, languages.short{f(EsField)}#14, last_name{f(KeywordEsField)}#15, salary{f(EsField)}#16, salary_change{f(EsField)}#17, salary_change.int{f(EsField)}#18, salary_change.keyword{f(KeywordEsField)}#19, salary_change.long{f(EsField)}#20, still_hired{f(EsField)}#21]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#22, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21, does_not_exist_field{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/query.esql new file mode 100644 index 0000000000000..0b9aa5a1c9b86 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| DROP emp_*, does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected new file mode 100644 index 0000000000000..9b31329838788 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, first_name{f(KeywordEsField)}#2, gender{f(KeywordEsField)}#3, height{f(EsField)}#4, height.float{f(EsField)}#5, height.half_float{f(EsField)}#6, height.scaled_float{f(EsField)}#7, hire_date{f(DateEsField)}#8, is_rehired{f(EsField)}#9, job_positions{f(KeywordEsField)}#10, languages{f(EsField)}#11, languages.byte{f(EsField)}#12, languages.long{f(EsField)}#13, languages.short{f(EsField)}#14, last_name{f(KeywordEsField)}#15, salary{f(EsField)}#16, salary_change{f(EsField)}#17, salary_change.int{f(EsField)}#18, salary_change.keyword{f(KeywordEsField)}#19, salary_change.long{f(EsField)}#20, still_hired{f(EsField)}#21]] + \_Eval[[null[NULL] AS does_not_exist_field#22]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#23, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/query.esql new file mode 100644 index 0000000000000..7064d202cbedc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| DROP emp_*, does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/load/analysis.expected new file mode 100644 index 0000000000000..26eeae08a3eb3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(does_not_exist_field{f}#0) + 1[INTEGER] AS x#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/load/query.esql new file mode 100644 index 0000000000000..f4ebacdf1a902 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| EVAL x = does_not_exist_field::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/analysis.expected new file mode 100644 index 0000000000000..58562d7c829d1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(does_not_exist_field{r}#0) + 1[INTEGER] AS x#1]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/query.esql new file mode 100644 index 0000000000000..8a1085423e2ed --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEval/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL x = does_not_exist_field::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/analysis.expected new file mode 100644 index 0000000000000..8f5d075d36aaf --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(does_not_exist_field{f}#0) + 2[INTEGER] AS y#1]] + \_Eval[[emp_no{f}#2 + 1[INTEGER] AS x#3]] + \_Project[[avg_worked_seconds{f(EsField)}#4, birth_date{f(DateEsField)}#5, emp_no{f(EsField)}#2, first_name{f(KeywordEsField)}#6, gender{f(KeywordEsField)}#7, height{f(EsField)}#8, height.float{f(EsField)}#9, height.half_float{f(EsField)}#10, height.scaled_float{f(EsField)}#11, hire_date{f(DateEsField)}#12, is_rehired{f(EsField)}#13, job_positions{f(KeywordEsField)}#14, languages{f(EsField)}#15, languages.byte{f(EsField)}#16, languages.long{f(EsField)}#17, languages.short{f(EsField)}#18, last_name{f(KeywordEsField)}#19, salary{f(EsField)}#20, salary_change{f(EsField)}#21, salary_change.int{f(EsField)}#22, salary_change.keyword{f(KeywordEsField)}#23, salary_change.long{f(EsField)}#24, still_hired{f(EsField)}#25, does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/query.esql new file mode 100644 index 0000000000000..dcd26bdd54bf4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees +| KEEP * +| EVAL x = emp_no + 1 +| EVAL y = does_not_exist_field::DOUBLE + 2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/analysis.expected new file mode 100644 index 0000000000000..2b90aac6121b2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/analysis.expected @@ -0,0 +1,6 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(does_not_exist_field{r}#0) + 2[INTEGER] AS y#1]] + \_Eval[[emp_no{f}#2 + 1[INTEGER] AS x#3]] + \_Project[[avg_worked_seconds{f(EsField)}#4, birth_date{f(DateEsField)}#5, emp_no{f(EsField)}#2, first_name{f(KeywordEsField)}#6, gender{f(KeywordEsField)}#7, height{f(EsField)}#8, height.float{f(EsField)}#9, height.half_float{f(EsField)}#10, height.scaled_float{f(EsField)}#11, hire_date{f(DateEsField)}#12, is_rehired{f(EsField)}#13, job_positions{f(KeywordEsField)}#14, languages{f(EsField)}#15, languages.byte{f(EsField)}#16, languages.long{f(EsField)}#17, languages.short{f(EsField)}#18, last_name{f(KeywordEsField)}#19, salary{f(EsField)}#20, salary_change{f(EsField)}#21, salary_change.int{f(EsField)}#22, salary_change.keyword{f(KeywordEsField)}#23, salary_change.long{f(EsField)}#24, still_hired{f(EsField)}#25, does_not_exist_field{r}#0]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/query.esql new file mode 100644 index 0000000000000..6f6ce85c55b54 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterKeepStar/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees +| KEEP * +| EVAL x = emp_no + 1 +| EVAL y = does_not_exist_field::DOUBLE + 2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/analysis.expected new file mode 100644 index 0000000000000..14e653fae9924 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(emp_does_not_exist_field{f}#0) + 2[INTEGER] AS y#1]] + \_Eval[[emp_no{f}#2 + 1[INTEGER] AS x#3]] + \_Project[[emp_no{f(EsField)}#2, avg_worked_seconds{f(EsField)}#4, birth_date{f(DateEsField)}#5, first_name{f(KeywordEsField)}#6, gender{f(KeywordEsField)}#7, height{f(EsField)}#8, height.float{f(EsField)}#9, height.half_float{f(EsField)}#10, height.scaled_float{f(EsField)}#11, hire_date{f(DateEsField)}#12, is_rehired{f(EsField)}#13, job_positions{f(KeywordEsField)}#14, languages{f(EsField)}#15, languages.byte{f(EsField)}#16, languages.long{f(EsField)}#17, languages.short{f(EsField)}#18, last_name{f(KeywordEsField)}#19, salary{f(EsField)}#20, salary_change{f(EsField)}#21, salary_change.int{f(EsField)}#22, salary_change.keyword{f(KeywordEsField)}#23, salary_change.long{f(EsField)}#24, still_hired{f(EsField)}#25, emp_does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, emp_does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/query.esql new file mode 100644 index 0000000000000..598a0d6552097 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees +| KEEP emp_no, * +| EVAL x = emp_no + 1 +| EVAL y = emp_does_not_exist_field::DOUBLE + 2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/analysis.expected new file mode 100644 index 0000000000000..87cf671c0534f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/analysis.expected @@ -0,0 +1,6 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(emp_does_not_exist_field{r}#0) + 2[INTEGER] AS y#1]] + \_Eval[[emp_no{f}#2 + 1[INTEGER] AS x#3]] + \_Project[[emp_no{f(EsField)}#2, avg_worked_seconds{f(EsField)}#4, birth_date{f(DateEsField)}#5, first_name{f(KeywordEsField)}#6, gender{f(KeywordEsField)}#7, height{f(EsField)}#8, height.float{f(EsField)}#9, height.half_float{f(EsField)}#10, height.scaled_float{f(EsField)}#11, hire_date{f(DateEsField)}#12, is_rehired{f(EsField)}#13, job_positions{f(KeywordEsField)}#14, languages{f(EsField)}#15, languages.byte{f(EsField)}#16, languages.long{f(EsField)}#17, languages.short{f(EsField)}#18, last_name{f(KeywordEsField)}#19, salary{f(EsField)}#20, salary_change{f(EsField)}#21, salary_change.int{f(EsField)}#22, salary_change.keyword{f(KeywordEsField)}#23, salary_change.long{f(EsField)}#24, still_hired{f(EsField)}#25, emp_does_not_exist_field{r}#0]] + \_Eval[[null[NULL] AS emp_does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/query.esql new file mode 100644 index 0000000000000..b96afd6be3bc8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAfterMatchingKeepWithWildcard/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees +| KEEP emp_no, * +| EVAL x = emp_no + 1 +| EVAL y = emp_does_not_exist_field::DOUBLE + 2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/analysis.expected new file mode 100644 index 0000000000000..9639c04a04474 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[does_not_exist_field1{f(PotentiallyUnmappedKeywordEsField)}#0, does_not_exist_field2{f(PotentiallyUnmappedKeywordEsField)}#1]] + \_Eval[[TOINTEGER(does_not_exist_field1{f}#0) + 42[INTEGER] AS x#2]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field1{f}#0, does_not_exist_field2{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/query.esql new file mode 100644 index 0000000000000..2a2c4f3dea742 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| EVAL x = does_not_exist_field1::INTEGER + 42 +| KEEP does_not_exist_field1, does_not_exist_field2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/analysis.expected new file mode 100644 index 0000000000000..93470d82bb0f9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Project[[does_not_exist_field1{r}#0, does_not_exist_field2{r}#1]] + \_Eval[[TOINTEGER(does_not_exist_field1{r}#0) + 42[INTEGER] AS x#2]] + \_Eval[[null[NULL] AS does_not_exist_field1#0, null[NULL] AS does_not_exist_field2#1]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/query.esql new file mode 100644 index 0000000000000..b835bd71bd018 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalAndKeep/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL x = does_not_exist_field1::INTEGER + 42 +| KEEP does_not_exist_field1, does_not_exist_field2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected new file mode 100644 index 0000000000000..93fe00d388c1d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TOLONG(does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0) AS x#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/query.esql new file mode 100644 index 0000000000000..f26a0fbca818e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| EVAL x = does_not_exist_field::LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/analysis.expected new file mode 100644 index 0000000000000..94776e53044a1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TOLONG(does_not_exist_field{r}#0) AS x#1]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/query.esql new file mode 100644 index 0000000000000..645643aa1255c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL x = does_not_exist_field::LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected new file mode 100644 index 0000000000000..1057b571c78de --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TOLONG(does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0) AS does_not_exist_field::LONG#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/query.esql new file mode 100644 index 0000000000000..fde7a9a40d5e3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| EVAL does_not_exist_field::LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/analysis.expected new file mode 100644 index 0000000000000..8b534e63aaf3c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TOLONG(does_not_exist_field{r}#0) AS does_not_exist_field::LONG#1]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/query.esql new file mode 100644 index 0000000000000..91f24cce1fb92 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL does_not_exist_field::LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected new file mode 100644 index 0000000000000..ffb2c79dd6cd0 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[42[INTEGER] AS does_not_exist_field#0]] + \_Eval[[TODOUBLE(does_not_exist_field{f}#1) + 1[INTEGER] AS x#2]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/query.esql new file mode 100644 index 0000000000000..826ae0ac8f745 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| EVAL x = does_not_exist_field::DOUBLE + 1 +| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected new file mode 100644 index 0000000000000..5ce8713e6a882 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[42[INTEGER] AS does_not_exist_field#0]] + \_Eval[[TODOUBLE(does_not_exist_field{r}#1) + 1[INTEGER] AS x#2]] + \_Eval[[null[NULL] AS does_not_exist_field#1]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql new file mode 100644 index 0000000000000..241e39491fa9a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL x = does_not_exist_field::DOUBLE + 1 +| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected new file mode 100644 index 0000000000000..1ea65e9515a9e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected @@ -0,0 +1,13 @@ +Limit[1000[INTEGER],false,false] +\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, _fork{r}#24]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#25, birth_date{f(DateEsField)}#26, emp_no{f(EsField)}#27, first_name{f(KeywordEsField)}#28, gender{f(KeywordEsField)}#29, height{f(EsField)}#30, height.float{f(EsField)}#31, height.half_float{f(EsField)}#32, height.scaled_float{f(EsField)}#33, hire_date{f(DateEsField)}#34, is_rehired{f(EsField)}#35, job_positions{f(KeywordEsField)}#36, languages{f(EsField)}#37, languages.byte{f(EsField)}#38, languages.long{f(EsField)}#39, languages.short{f(EsField)}#40, last_name{f(KeywordEsField)}#41, salary{f(EsField)}#42, salary_change{f(EsField)}#43, salary_change.int{f(EsField)}#44, salary_change.keyword{f(KeywordEsField)}#45, salary_change.long{f(EsField)}#46, still_hired{f(EsField)}#47, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#48, _fork{r}#49]] + | \_Eval[[fork1[KEYWORD] AS _fork#49]] + | \_Filter[TOLONG(does_not_exist{f}#48) > 0[INTEGER]] + | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, does_not_exist{f}#48] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#50, birth_date{f(DateEsField)}#51, emp_no{f(EsField)}#52, first_name{f(KeywordEsField)}#53, gender{f(KeywordEsField)}#54, height{f(EsField)}#55, height.float{f(EsField)}#56, height.half_float{f(EsField)}#57, height.scaled_float{f(EsField)}#58, hire_date{f(DateEsField)}#59, is_rehired{f(EsField)}#60, job_positions{f(KeywordEsField)}#61, languages{f(EsField)}#62, languages.byte{f(EsField)}#63, languages.long{f(EsField)}#64, languages.short{f(EsField)}#65, last_name{f(KeywordEsField)}#66, salary{f(EsField)}#67, salary_change{f(EsField)}#68, salary_change.int{f(EsField)}#69, salary_change.keyword{f(KeywordEsField)}#70, salary_change.long{f(EsField)}#71, still_hired{f(EsField)}#72, does_not_exist{r}#73, _fork{r}#49]] + \_Eval[[null[KEYWORD] AS does_not_exist#73]] + \_Eval[[fork2[KEYWORD] AS _fork#49]] + \_Filter[emp_no{f}#52 > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#50, birth_date{f}#51, emp_no{f}#52, first_name{f}#53, gender{f}#54, height{f}#55, height.float{f}#56, height.half_float{f}#57, height.scaled_float{f}#58, hire_date{f}#59, is_rehired{f}#60, job_positions{f}#61, languages{f}#62, languages.byte{f}#63, languages.long{f}#64, languages.short{f}#65, last_name{f}#66, salary{f}#67, salary_change{f}#68, salary_change.int{f}#69, salary_change.keyword{f}#70, salary_change.long{f}#71, still_hired{f}#72] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql new file mode 100644 index 0000000000000..1b2a31d2f6afd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| FORK (WHERE does_not_exist::LONG > 0) + (WHERE emp_no > 0) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/analysis.expected new file mode 100644 index 0000000000000..bef6a1204b623 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/analysis.expected @@ -0,0 +1,14 @@ +Limit[1000[INTEGER],false,false] +\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, _fork{r}#24]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#25, birth_date{f(DateEsField)}#26, emp_no{f(EsField)}#27, first_name{f(KeywordEsField)}#28, gender{f(KeywordEsField)}#29, height{f(EsField)}#30, height.float{f(EsField)}#31, height.half_float{f(EsField)}#32, height.scaled_float{f(EsField)}#33, hire_date{f(DateEsField)}#34, is_rehired{f(EsField)}#35, job_positions{f(KeywordEsField)}#36, languages{f(EsField)}#37, languages.byte{f(EsField)}#38, languages.long{f(EsField)}#39, languages.short{f(EsField)}#40, last_name{f(KeywordEsField)}#41, salary{f(EsField)}#42, salary_change{f(EsField)}#43, salary_change.int{f(EsField)}#44, salary_change.keyword{f(KeywordEsField)}#45, salary_change.long{f(EsField)}#46, still_hired{f(EsField)}#47, does_not_exist{r}#48, _fork{r}#49]] + | \_Eval[[fork1[KEYWORD] AS _fork#49]] + | \_Filter[TOLONG(does_not_exist{r}#48) > 0[INTEGER]] + | \_Eval[[null[NULL] AS does_not_exist#48]] + | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#50, birth_date{f(DateEsField)}#51, emp_no{f(EsField)}#52, first_name{f(KeywordEsField)}#53, gender{f(KeywordEsField)}#54, height{f(EsField)}#55, height.float{f(EsField)}#56, height.half_float{f(EsField)}#57, height.scaled_float{f(EsField)}#58, hire_date{f(DateEsField)}#59, is_rehired{f(EsField)}#60, job_positions{f(KeywordEsField)}#61, languages{f(EsField)}#62, languages.byte{f(EsField)}#63, languages.long{f(EsField)}#64, languages.short{f(EsField)}#65, last_name{f(KeywordEsField)}#66, salary{f(EsField)}#67, salary_change{f(EsField)}#68, salary_change.int{f(EsField)}#69, salary_change.keyword{f(KeywordEsField)}#70, salary_change.long{f(EsField)}#71, still_hired{f(EsField)}#72, does_not_exist{r}#73, _fork{r}#49]] + \_Eval[[null[NULL] AS does_not_exist#73]] + \_Eval[[fork2[KEYWORD] AS _fork#49]] + \_Filter[emp_no{f}#52 > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#50, birth_date{f}#51, emp_no{f}#52, first_name{f}#53, gender{f}#54, height{f}#55, height.float{f}#56, height.half_float{f}#57, height.scaled_float{f}#58, hire_date{f}#59, is_rehired{f}#60, job_positions{f}#61, languages{f}#62, languages.byte{f}#63, languages.long{f}#64, languages.short{f}#65, last_name{f}#66, salary{f}#67, salary_change{f}#68, salary_change.int{f}#69, salary_change.keyword{f}#70, salary_change.long{f}#71, still_hired{f}#72] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/query.esql new file mode 100644 index 0000000000000..f52a0ffff2847 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| FORK (WHERE does_not_exist::LONG > 0) + (WHERE emp_no > 0) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected new file mode 100644 index 0000000000000..312bfbd84c8b9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected @@ -0,0 +1,14 @@ +Limit[1000[INTEGER],false,false] +\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, x{r}#24, _fork{r}#25, y{r}#26]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#27, birth_date{f(DateEsField)}#28, emp_no{f(EsField)}#29, first_name{f(KeywordEsField)}#30, gender{f(KeywordEsField)}#31, height{f(EsField)}#32, height.float{f(EsField)}#33, height.half_float{f(EsField)}#34, height.scaled_float{f(EsField)}#35, hire_date{f(DateEsField)}#36, is_rehired{f(EsField)}#37, job_positions{f(KeywordEsField)}#38, languages{f(EsField)}#39, languages.byte{f(EsField)}#40, languages.long{f(EsField)}#41, languages.short{f(EsField)}#42, last_name{f(KeywordEsField)}#43, salary{f(EsField)}#44, salary_change{f(EsField)}#45, salary_change.int{f(EsField)}#46, salary_change.keyword{f(KeywordEsField)}#47, salary_change.long{f(EsField)}#48, still_hired{f(EsField)}#49, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#50, x{r}#51, _fork{r}#52, y{r}#53]] + | \_Eval[[null[INTEGER] AS y#53]] + | \_Eval[[fork1[KEYWORD] AS _fork#52]] + | \_Eval[[TODOUBLE(does_not_exist{f}#50) + 1[INTEGER] AS x#51]] + | \_EsRelation[employees][avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, does_not_exist{f}#50] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#54, birth_date{f(DateEsField)}#55, emp_no{f(EsField)}#56, first_name{f(KeywordEsField)}#57, gender{f(KeywordEsField)}#58, height{f(EsField)}#59, height.float{f(EsField)}#60, height.half_float{f(EsField)}#61, height.scaled_float{f(EsField)}#62, hire_date{f(DateEsField)}#63, is_rehired{f(EsField)}#64, job_positions{f(KeywordEsField)}#65, languages{f(EsField)}#66, languages.byte{f(EsField)}#67, languages.long{f(EsField)}#68, languages.short{f(EsField)}#69, last_name{f(KeywordEsField)}#70, salary{f(EsField)}#71, salary_change{f(EsField)}#72, salary_change.int{f(EsField)}#73, salary_change.keyword{f(KeywordEsField)}#74, salary_change.long{f(EsField)}#75, still_hired{f(EsField)}#76, does_not_exist{r}#77, x{r}#78, _fork{r}#52, y{r}#79]] + \_Eval[[null[KEYWORD] AS does_not_exist#77, null[DOUBLE] AS x#78]] + \_Eval[[fork2[KEYWORD] AS _fork#52]] + \_Eval[[emp_no{f}#56 + 1[INTEGER] AS y#79]] + \_EsRelation[employees][avg_worked_seconds{f}#54, birth_date{f}#55, emp_no{f}#56, first_name{f}#57, gender{f}#58, height{f}#59, height.float{f}#60, height.half_float{f}#61, height.scaled_float{f}#62, hire_date{f}#63, is_rehired{f}#64, job_positions{f}#65, languages{f}#66, languages.byte{f}#67, languages.long{f}#68, languages.short{f}#69, last_name{f}#70, salary{f}#71, salary_change{f}#72, salary_change.int{f}#73, salary_change.keyword{f}#74, salary_change.long{f}#75, still_hired{f}#76] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql new file mode 100644 index 0000000000000..f007f2dec96ca --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| FORK (EVAL x = does_not_exist::DOUBLE + 1) + (EVAL y = emp_no + 1) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/analysis.expected new file mode 100644 index 0000000000000..c02033434bdb1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/analysis.expected @@ -0,0 +1,15 @@ +Limit[1000[INTEGER],false,false] +\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, x{r}#24, _fork{r}#25, y{r}#26]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#27, birth_date{f(DateEsField)}#28, emp_no{f(EsField)}#29, first_name{f(KeywordEsField)}#30, gender{f(KeywordEsField)}#31, height{f(EsField)}#32, height.float{f(EsField)}#33, height.half_float{f(EsField)}#34, height.scaled_float{f(EsField)}#35, hire_date{f(DateEsField)}#36, is_rehired{f(EsField)}#37, job_positions{f(KeywordEsField)}#38, languages{f(EsField)}#39, languages.byte{f(EsField)}#40, languages.long{f(EsField)}#41, languages.short{f(EsField)}#42, last_name{f(KeywordEsField)}#43, salary{f(EsField)}#44, salary_change{f(EsField)}#45, salary_change.int{f(EsField)}#46, salary_change.keyword{f(KeywordEsField)}#47, salary_change.long{f(EsField)}#48, still_hired{f(EsField)}#49, does_not_exist{r}#50, x{r}#51, _fork{r}#52, y{r}#53]] + | \_Eval[[null[INTEGER] AS y#53]] + | \_Eval[[fork1[KEYWORD] AS _fork#52]] + | \_Eval[[TODOUBLE(does_not_exist{r}#50) + 1[INTEGER] AS x#51]] + | \_Eval[[null[NULL] AS does_not_exist#50]] + | \_EsRelation[employees][avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#54, birth_date{f(DateEsField)}#55, emp_no{f(EsField)}#56, first_name{f(KeywordEsField)}#57, gender{f(KeywordEsField)}#58, height{f(EsField)}#59, height.float{f(EsField)}#60, height.half_float{f(EsField)}#61, height.scaled_float{f(EsField)}#62, hire_date{f(DateEsField)}#63, is_rehired{f(EsField)}#64, job_positions{f(KeywordEsField)}#65, languages{f(EsField)}#66, languages.byte{f(EsField)}#67, languages.long{f(EsField)}#68, languages.short{f(EsField)}#69, last_name{f(KeywordEsField)}#70, salary{f(EsField)}#71, salary_change{f(EsField)}#72, salary_change.int{f(EsField)}#73, salary_change.keyword{f(KeywordEsField)}#74, salary_change.long{f(EsField)}#75, still_hired{f(EsField)}#76, does_not_exist{r}#77, x{r}#78, _fork{r}#52, y{r}#79]] + \_Eval[[null[NULL] AS does_not_exist#77, null[DOUBLE] AS x#78]] + \_Eval[[fork2[KEYWORD] AS _fork#52]] + \_Eval[[emp_no{f}#56 + 1[INTEGER] AS y#79]] + \_EsRelation[employees][avg_worked_seconds{f}#54, birth_date{f}#55, emp_no{f}#56, first_name{f}#57, gender{f}#58, height{f}#59, height.float{f}#60, height.half_float{f}#61, height.scaled_float{f}#62, hire_date{f}#63, is_rehired{f}#64, job_positions{f}#65, languages{f}#66, languages.byte{f}#67, languages.long{f}#68, languages.short{f}#69, last_name{f}#70, salary{f}#71, salary_change{f}#72, salary_change.int{f}#73, salary_change.keyword{f}#74, salary_change.long{f}#75, still_hired{f}#76] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/query.esql new file mode 100644 index 0000000000000..70e809476f257 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| FORK (EVAL x = does_not_exist::DOUBLE + 1) + (EVAL y = emp_no + 1) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected new file mode 100644 index 0000000000000..3c38b14082b60 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected @@ -0,0 +1,15 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[does_not_exist{r}#0,ASC,LAST]]] + \_Fork[[c{r}#1, does_not_exist{r}#0, _fork{r}#2, d{r}#3]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[c{r}#4, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#5, _fork{r}#6, d{r}#7]] + | \_Eval[[null[DOUBLE] AS d#7]] + | \_Eval[[fork1[KEYWORD] AS _fork#6]] + | \_Aggregate[[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#5],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#5]] + | \_EsRelation[employees][avg_worked_seconds{f}#8, birth_date{f}#9, emp_no{f}#10, first_name{f}#11, gender{f}#12, height{f}#13, height.float{f}#14, height.half_float{f}#15, height.scaled_float{f}#16, hire_date{f}#17, is_rehired{f}#18, job_positions{f}#19, languages{f}#20, languages.byte{f}#21, languages.long{f}#22, languages.short{f}#23, last_name{f}#24, salary{f}#25, salary_change{f}#26, salary_change.int{f}#27, salary_change.keyword{f}#28, salary_change.long{f}#29, still_hired{f}#30, does_not_exist{f}#5] + \_Limit[1000[INTEGER],false,false] + \_Project[[c{r}#31, does_not_exist{r}#32, _fork{r}#6, d{r}#33]] + \_Eval[[null[LONG] AS c#31, null[KEYWORD] AS does_not_exist#32]] + \_Eval[[fork2[KEYWORD] AS _fork#6]] + \_Aggregate[[],[AVG(TODOUBLE(salary{f(EsField)}#34),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS d#33]] + \_EsRelation[employees][avg_worked_seconds{f}#35, birth_date{f}#36, emp_no{f}#37, first_name{f}#38, gender{f}#39, height{f}#40, height.float{f}#41, height.half_float{f}#42, height.scaled_float{f}#43, hire_date{f}#44, is_rehired{f}#45, job_positions{f}#46, languages{f}#47, languages.byte{f}#48, languages.long{f}#49, languages.short{f}#50, last_name{f}#51, salary{f}#34, salary_change{f}#52, salary_change.int{f}#53, salary_change.keyword{f}#54, salary_change.long{f}#55, still_hired{f}#56] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql new file mode 100644 index 0000000000000..3a52496cdfc84 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees +| FORK (STATS c = COUNT(*) BY does_not_exist) + (STATS d = AVG(salary::DOUBLE)) +| SORT does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/analysis.expected new file mode 100644 index 0000000000000..2b609c20b89e9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/analysis.expected @@ -0,0 +1,16 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[does_not_exist{r}#0,ASC,LAST]]] + \_Fork[[c{r}#1, does_not_exist{r}#0, _fork{r}#2, d{r}#3]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[c{r}#4, does_not_exist{r}#5, _fork{r}#6, d{r}#7]] + | \_Eval[[null[DOUBLE] AS d#7]] + | \_Eval[[fork1[KEYWORD] AS _fork#6]] + | \_Aggregate[[does_not_exist{r}#5],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist{r}#5]] + | \_Eval[[null[NULL] AS does_not_exist#5]] + | \_EsRelation[employees][avg_worked_seconds{f}#8, birth_date{f}#9, emp_no{f}#10, first_name{f}#11, gender{f}#12, height{f}#13, height.float{f}#14, height.half_float{f}#15, height.scaled_float{f}#16, hire_date{f}#17, is_rehired{f}#18, job_positions{f}#19, languages{f}#20, languages.byte{f}#21, languages.long{f}#22, languages.short{f}#23, last_name{f}#24, salary{f}#25, salary_change{f}#26, salary_change.int{f}#27, salary_change.keyword{f}#28, salary_change.long{f}#29, still_hired{f}#30] + \_Limit[1000[INTEGER],false,false] + \_Project[[c{r}#31, does_not_exist{r}#32, _fork{r}#6, d{r}#33]] + \_Eval[[null[LONG] AS c#31, null[NULL] AS does_not_exist#32]] + \_Eval[[fork2[KEYWORD] AS _fork#6]] + \_Aggregate[[],[AVG(TODOUBLE(salary{f(EsField)}#34),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS d#33]] + \_EsRelation[employees][avg_worked_seconds{f}#35, birth_date{f}#36, emp_no{f}#37, first_name{f}#38, gender{f}#39, height{f}#40, height.float{f}#41, height.half_float{f}#42, height.scaled_float{f}#43, hire_date{f}#44, is_rehired{f}#45, job_positions{f}#46, languages{f}#47, languages.byte{f}#48, languages.long{f}#49, languages.short{f}#50, last_name{f}#51, salary{f}#34, salary_change{f}#52, salary_change.int{f}#53, salary_change.keyword{f}#54, salary_change.long{f}#55, still_hired{f}#56] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/query.esql new file mode 100644 index 0000000000000..e6d155e05a41b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees +| FORK (STATS c = COUNT(*) BY does_not_exist) + (STATS d = AVG(salary::DOUBLE)) +| SORT does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected new file mode 100644 index 0000000000000..f34822d2c1c68 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected @@ -0,0 +1,15 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(_fork{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#55]] + \_FuseScoreEval[_score{r}#2,_fork{r}#54,RRF,null] + \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, _fork{r}#54]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#56, birth_date{f(DateEsField)}#57, emp_no{f(EsField)}#58, first_name{f(KeywordEsField)}#59, gender{f(KeywordEsField)}#60, height{f(EsField)}#61, height.float{f(EsField)}#62, height.half_float{f(EsField)}#63, height.scaled_float{f(EsField)}#64, hire_date{f(DateEsField)}#65, is_rehired{f(EsField)}#66, job_positions{f(KeywordEsField)}#67, languages{f(EsField)}#68, languages.byte{f(EsField)}#69, languages.long{f(EsField)}#70, languages.short{f(EsField)}#71, last_name{f(KeywordEsField)}#72, salary{f(EsField)}#73, salary_change{f(EsField)}#74, salary_change.int{f(EsField)}#75, salary_change.keyword{f(KeywordEsField)}#76, salary_change.long{f(EsField)}#77, still_hired{f(EsField)}#78, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#82, _fork{r}#83]] + | \_Eval[[fork1[KEYWORD] AS _fork#83]] + | \_Filter[TOLONG(does_not_exist{f}#82) > 0[INTEGER]] + | \_EsRelation[employees][avg_worked_seconds{f}#56, birth_date{f}#57, emp_no{f}#58, first_name{f}#59, gender{f}#60, height{f}#61, height.float{f}#62, height.half_float{f}#63, height.scaled_float{f}#64, hire_date{f}#65, is_rehired{f}#66, job_positions{f}#67, languages{f}#68, languages.byte{f}#69, languages.long{f}#70, languages.short{f}#71, last_name{f}#72, salary{f}#73, salary_change{f}#74, salary_change.int{f}#75, salary_change.keyword{f}#76, salary_change.long{f}#77, still_hired{f}#78, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{f}#82] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#84, birth_date{f(DateEsField)}#85, emp_no{f(EsField)}#86, first_name{f(KeywordEsField)}#87, gender{f(KeywordEsField)}#88, height{f(EsField)}#89, height.float{f(EsField)}#90, height.half_float{f(EsField)}#91, height.scaled_float{f(EsField)}#92, hire_date{f(DateEsField)}#93, is_rehired{f(EsField)}#94, job_positions{f(KeywordEsField)}#95, languages{f(EsField)}#96, languages.byte{f(EsField)}#97, languages.long{f(EsField)}#98, languages.short{f(EsField)}#99, last_name{f(KeywordEsField)}#100, salary{f(EsField)}#101, salary_change{f(EsField)}#102, salary_change.int{f(EsField)}#103, salary_change.keyword{f(KeywordEsField)}#104, salary_change.long{f(EsField)}#105, still_hired{f(EsField)}#106, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{r}#107, _fork{r}#83]] + \_Eval[[null[KEYWORD] AS does_not_exist#107]] + \_Eval[[fork2[KEYWORD] AS _fork#83]] + \_Filter[emp_no{f}#86 > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#84, birth_date{f}#85, emp_no{f}#86, first_name{f}#87, gender{f}#88, height{f}#89, height.float{f}#90, height.half_float{f}#91, height.scaled_float{f}#92, hire_date{f}#93, is_rehired{f}#94, job_positions{f}#95, languages{f}#96, languages.byte{f}#97, languages.long{f}#98, languages.short{f}#99, last_name{f}#100, salary{f}#101, salary_change{f}#102, salary_change.int{f}#103, salary_change.keyword{f}#104, salary_change.long{f}#105, still_hired{f}#106, _score{m}#79, _index{m}#80, _id{m}#81] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql new file mode 100644 index 0000000000000..2217f682e64de --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees METADATA _score, _index, _id +| FORK (WHERE does_not_exist::LONG > 0) + (WHERE emp_no > 0) +| FUSE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/analysis.expected new file mode 100644 index 0000000000000..cfa9ace9ad952 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/analysis.expected @@ -0,0 +1,16 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(_fork{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#55]] + \_FuseScoreEval[_score{r}#2,_fork{r}#54,RRF,null] + \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, _fork{r}#54]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#56, birth_date{f(DateEsField)}#57, emp_no{f(EsField)}#58, first_name{f(KeywordEsField)}#59, gender{f(KeywordEsField)}#60, height{f(EsField)}#61, height.float{f(EsField)}#62, height.half_float{f(EsField)}#63, height.scaled_float{f(EsField)}#64, hire_date{f(DateEsField)}#65, is_rehired{f(EsField)}#66, job_positions{f(KeywordEsField)}#67, languages{f(EsField)}#68, languages.byte{f(EsField)}#69, languages.long{f(EsField)}#70, languages.short{f(EsField)}#71, last_name{f(KeywordEsField)}#72, salary{f(EsField)}#73, salary_change{f(EsField)}#74, salary_change.int{f(EsField)}#75, salary_change.keyword{f(KeywordEsField)}#76, salary_change.long{f(EsField)}#77, still_hired{f(EsField)}#78, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{r}#82, _fork{r}#83]] + | \_Eval[[fork1[KEYWORD] AS _fork#83]] + | \_Filter[TOLONG(does_not_exist{r}#82) > 0[INTEGER]] + | \_Eval[[null[NULL] AS does_not_exist#82]] + | \_EsRelation[employees][avg_worked_seconds{f}#56, birth_date{f}#57, emp_no{f}#58, first_name{f}#59, gender{f}#60, height{f}#61, height.float{f}#62, height.half_float{f}#63, height.scaled_float{f}#64, hire_date{f}#65, is_rehired{f}#66, job_positions{f}#67, languages{f}#68, languages.byte{f}#69, languages.long{f}#70, languages.short{f}#71, last_name{f}#72, salary{f}#73, salary_change{f}#74, salary_change.int{f}#75, salary_change.keyword{f}#76, salary_change.long{f}#77, still_hired{f}#78, _score{m}#79, _index{m}#80, _id{m}#81] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#84, birth_date{f(DateEsField)}#85, emp_no{f(EsField)}#86, first_name{f(KeywordEsField)}#87, gender{f(KeywordEsField)}#88, height{f(EsField)}#89, height.float{f(EsField)}#90, height.half_float{f(EsField)}#91, height.scaled_float{f(EsField)}#92, hire_date{f(DateEsField)}#93, is_rehired{f(EsField)}#94, job_positions{f(KeywordEsField)}#95, languages{f(EsField)}#96, languages.byte{f(EsField)}#97, languages.long{f(EsField)}#98, languages.short{f(EsField)}#99, last_name{f(KeywordEsField)}#100, salary{f(EsField)}#101, salary_change{f(EsField)}#102, salary_change.int{f(EsField)}#103, salary_change.keyword{f(KeywordEsField)}#104, salary_change.long{f(EsField)}#105, still_hired{f(EsField)}#106, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{r}#107, _fork{r}#83]] + \_Eval[[null[NULL] AS does_not_exist#107]] + \_Eval[[fork2[KEYWORD] AS _fork#83]] + \_Filter[emp_no{f}#86 > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#84, birth_date{f}#85, emp_no{f}#86, first_name{f}#87, gender{f}#88, height{f}#89, height.float{f}#90, height.half_float{f}#91, height.scaled_float{f}#92, hire_date{f}#93, is_rehired{f}#94, job_positions{f}#95, languages{f}#96, languages.byte{f}#97, languages.long{f}#98, languages.short{f}#99, last_name{f}#100, salary{f}#101, salary_change{f}#102, salary_change.int{f}#103, salary_change.keyword{f}#104, salary_change.long{f}#105, still_hired{f}#106, _score{m}#79, _index{m}#80, _id{m}#81] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/query.esql new file mode 100644 index 0000000000000..53465ff6db0c5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees METADATA _score, _index, _id +| FORK (WHERE does_not_exist::LONG > 0) + (WHERE emp_no > 0) +| FUSE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected new file mode 100644 index 0000000000000..04da9a423e8dc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected @@ -0,0 +1,18 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(x{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS x#55, VALUES(_fork{r}#56,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#57, VALUES(y{r}#58,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#59]] + \_FuseScoreEval[_score{r}#2,_fork{r}#56,LINEAR,null] + \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, x{r}#54, _fork{r}#56, y{r}#58]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#60, birth_date{f(DateEsField)}#61, emp_no{f(EsField)}#62, first_name{f(KeywordEsField)}#63, gender{f(KeywordEsField)}#64, height{f(EsField)}#65, height.float{f(EsField)}#66, height.half_float{f(EsField)}#67, height.scaled_float{f(EsField)}#68, hire_date{f(DateEsField)}#69, is_rehired{f(EsField)}#70, job_positions{f(KeywordEsField)}#71, languages{f(EsField)}#72, languages.byte{f(EsField)}#73, languages.long{f(EsField)}#74, languages.short{f(EsField)}#75, last_name{f(KeywordEsField)}#76, salary{f(EsField)}#77, salary_change{f(EsField)}#78, salary_change.int{f(EsField)}#79, salary_change.keyword{f(KeywordEsField)}#80, salary_change.long{f(EsField)}#81, still_hired{f(EsField)}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#86, x{r}#87, _fork{r}#88, y{r}#89]] + | \_Eval[[null[INTEGER] AS y#89]] + | \_Eval[[fork1[KEYWORD] AS _fork#88]] + | \_Eval[[1[INTEGER] AS x#87]] + | \_Filter[TOLONG(does_not_exist{f}#86) > 0[INTEGER]] + | \_EsRelation[employees][avg_worked_seconds{f}#60, birth_date{f}#61, emp_no{f}#62, first_name{f}#63, gender{f}#64, height{f}#65, height.float{f}#66, height.half_float{f}#67, height.scaled_float{f}#68, hire_date{f}#69, is_rehired{f}#70, job_positions{f}#71, languages{f}#72, languages.byte{f}#73, languages.long{f}#74, languages.short{f}#75, last_name{f}#76, salary{f}#77, salary_change{f}#78, salary_change.int{f}#79, salary_change.keyword{f}#80, salary_change.long{f}#81, still_hired{f}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f}#86] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#90, birth_date{f(DateEsField)}#91, emp_no{f(EsField)}#92, first_name{f(KeywordEsField)}#93, gender{f(KeywordEsField)}#94, height{f(EsField)}#95, height.float{f(EsField)}#96, height.half_float{f(EsField)}#97, height.scaled_float{f(EsField)}#98, hire_date{f(DateEsField)}#99, is_rehired{f(EsField)}#100, job_positions{f(KeywordEsField)}#101, languages{f(EsField)}#102, languages.byte{f(EsField)}#103, languages.long{f(EsField)}#104, languages.short{f(EsField)}#105, last_name{f(KeywordEsField)}#106, salary{f(EsField)}#107, salary_change{f(EsField)}#108, salary_change.int{f(EsField)}#109, salary_change.keyword{f(KeywordEsField)}#110, salary_change.long{f(EsField)}#111, still_hired{f(EsField)}#112, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#113, x{r}#114, _fork{r}#88, y{r}#115]] + \_Eval[[null[KEYWORD] AS does_not_exist#113, null[INTEGER] AS x#114]] + \_Eval[[fork2[KEYWORD] AS _fork#88]] + \_Eval[[2[INTEGER] AS y#115]] + \_Filter[emp_no{f}#92 > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#90, birth_date{f}#91, emp_no{f}#92, first_name{f}#93, gender{f}#94, height{f}#95, height.float{f}#96, height.half_float{f}#97, height.scaled_float{f}#98, hire_date{f}#99, is_rehired{f}#100, job_positions{f}#101, languages{f}#102, languages.byte{f}#103, languages.long{f}#104, languages.short{f}#105, last_name{f}#106, salary{f}#107, salary_change{f}#108, salary_change.int{f}#109, salary_change.keyword{f}#110, salary_change.long{f}#111, still_hired{f}#112, _score{m}#83, _index{m}#84, _id{m}#85] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql new file mode 100644 index 0000000000000..6ca46384903c8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees METADATA _score, _index, _id +| FORK (WHERE does_not_exist::LONG > 0 | EVAL x = 1) + (WHERE emp_no > 0 | EVAL y = 2) +| FUSE LINEAR diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/analysis.expected new file mode 100644 index 0000000000000..2d4aef7657ab1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/analysis.expected @@ -0,0 +1,19 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(x{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS x#55, VALUES(_fork{r}#56,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#57, VALUES(y{r}#58,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#59]] + \_FuseScoreEval[_score{r}#2,_fork{r}#56,LINEAR,null] + \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, x{r}#54, _fork{r}#56, y{r}#58]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#60, birth_date{f(DateEsField)}#61, emp_no{f(EsField)}#62, first_name{f(KeywordEsField)}#63, gender{f(KeywordEsField)}#64, height{f(EsField)}#65, height.float{f(EsField)}#66, height.half_float{f(EsField)}#67, height.scaled_float{f(EsField)}#68, hire_date{f(DateEsField)}#69, is_rehired{f(EsField)}#70, job_positions{f(KeywordEsField)}#71, languages{f(EsField)}#72, languages.byte{f(EsField)}#73, languages.long{f(EsField)}#74, languages.short{f(EsField)}#75, last_name{f(KeywordEsField)}#76, salary{f(EsField)}#77, salary_change{f(EsField)}#78, salary_change.int{f(EsField)}#79, salary_change.keyword{f(KeywordEsField)}#80, salary_change.long{f(EsField)}#81, still_hired{f(EsField)}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#86, x{r}#87, _fork{r}#88, y{r}#89]] + | \_Eval[[null[INTEGER] AS y#89]] + | \_Eval[[fork1[KEYWORD] AS _fork#88]] + | \_Eval[[1[INTEGER] AS x#87]] + | \_Filter[TOLONG(does_not_exist{r}#86) > 0[INTEGER]] + | \_Eval[[null[NULL] AS does_not_exist#86]] + | \_EsRelation[employees][avg_worked_seconds{f}#60, birth_date{f}#61, emp_no{f}#62, first_name{f}#63, gender{f}#64, height{f}#65, height.float{f}#66, height.half_float{f}#67, height.scaled_float{f}#68, hire_date{f}#69, is_rehired{f}#70, job_positions{f}#71, languages{f}#72, languages.byte{f}#73, languages.long{f}#74, languages.short{f}#75, last_name{f}#76, salary{f}#77, salary_change{f}#78, salary_change.int{f}#79, salary_change.keyword{f}#80, salary_change.long{f}#81, still_hired{f}#82, _score{m}#83, _index{m}#84, _id{m}#85] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#90, birth_date{f(DateEsField)}#91, emp_no{f(EsField)}#92, first_name{f(KeywordEsField)}#93, gender{f(KeywordEsField)}#94, height{f(EsField)}#95, height.float{f(EsField)}#96, height.half_float{f(EsField)}#97, height.scaled_float{f(EsField)}#98, hire_date{f(DateEsField)}#99, is_rehired{f(EsField)}#100, job_positions{f(KeywordEsField)}#101, languages{f(EsField)}#102, languages.byte{f(EsField)}#103, languages.long{f(EsField)}#104, languages.short{f(EsField)}#105, last_name{f(KeywordEsField)}#106, salary{f(EsField)}#107, salary_change{f(EsField)}#108, salary_change.int{f(EsField)}#109, salary_change.keyword{f(KeywordEsField)}#110, salary_change.long{f(EsField)}#111, still_hired{f(EsField)}#112, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#113, x{r}#114, _fork{r}#88, y{r}#115]] + \_Eval[[null[NULL] AS does_not_exist#113, null[INTEGER] AS x#114]] + \_Eval[[fork2[KEYWORD] AS _fork#88]] + \_Eval[[2[INTEGER] AS y#115]] + \_Filter[emp_no{f}#92 > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#90, birth_date{f}#91, emp_no{f}#92, first_name{f}#93, gender{f}#94, height{f}#95, height.float{f}#96, height.half_float{f}#97, height.scaled_float{f}#98, hire_date{f}#99, is_rehired{f}#100, job_positions{f}#101, languages{f}#102, languages.byte{f}#103, languages.long{f}#104, languages.short{f}#105, last_name{f}#106, salary{f}#107, salary_change{f}#108, salary_change.int{f}#109, salary_change.keyword{f}#110, salary_change.long{f}#111, still_hired{f}#112, _score{m}#83, _index{m}#84, _id{m}#85] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/query.esql new file mode 100644 index 0000000000000..b4201b56e3cf8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees METADATA _score, _index, _id +| FORK (WHERE does_not_exist::LONG > 0 | EVAL x = 1) + (WHERE emp_no > 0 | EVAL y = 2) +| FUSE LINEAR diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected new file mode 100644 index 0000000000000..bc41c8f49b9f2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected @@ -0,0 +1,16 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(x{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS x#55, VALUES(_fork{r}#56,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#57, VALUES(y{r}#58,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#59]] + \_FuseScoreEval[_score{r}#2,_fork{r}#56,RRF,null] + \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, x{r}#54, _fork{r}#56, y{r}#58]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#60, birth_date{f(DateEsField)}#61, emp_no{f(EsField)}#62, first_name{f(KeywordEsField)}#63, gender{f(KeywordEsField)}#64, height{f(EsField)}#65, height.float{f(EsField)}#66, height.half_float{f(EsField)}#67, height.scaled_float{f(EsField)}#68, hire_date{f(DateEsField)}#69, is_rehired{f(EsField)}#70, job_positions{f(KeywordEsField)}#71, languages{f(EsField)}#72, languages.byte{f(EsField)}#73, languages.long{f(EsField)}#74, languages.short{f(EsField)}#75, last_name{f(KeywordEsField)}#76, salary{f(EsField)}#77, salary_change{f(EsField)}#78, salary_change.int{f(EsField)}#79, salary_change.keyword{f(KeywordEsField)}#80, salary_change.long{f(EsField)}#81, still_hired{f(EsField)}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#86, x{r}#87, _fork{r}#88, y{r}#89]] + | \_Eval[[null[INTEGER] AS y#89]] + | \_Eval[[fork1[KEYWORD] AS _fork#88]] + | \_Eval[[TODOUBLE(does_not_exist{f}#86) + 1[INTEGER] AS x#87]] + | \_EsRelation[employees][avg_worked_seconds{f}#60, birth_date{f}#61, emp_no{f}#62, first_name{f}#63, gender{f}#64, height{f}#65, height.float{f}#66, height.half_float{f}#67, height.scaled_float{f}#68, hire_date{f}#69, is_rehired{f}#70, job_positions{f}#71, languages{f}#72, languages.byte{f}#73, languages.long{f}#74, languages.short{f}#75, last_name{f}#76, salary{f}#77, salary_change{f}#78, salary_change.int{f}#79, salary_change.keyword{f}#80, salary_change.long{f}#81, still_hired{f}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f}#86] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#90, birth_date{f(DateEsField)}#91, emp_no{f(EsField)}#92, first_name{f(KeywordEsField)}#93, gender{f(KeywordEsField)}#94, height{f(EsField)}#95, height.float{f(EsField)}#96, height.half_float{f(EsField)}#97, height.scaled_float{f(EsField)}#98, hire_date{f(DateEsField)}#99, is_rehired{f(EsField)}#100, job_positions{f(KeywordEsField)}#101, languages{f(EsField)}#102, languages.byte{f(EsField)}#103, languages.long{f(EsField)}#104, languages.short{f(EsField)}#105, last_name{f(KeywordEsField)}#106, salary{f(EsField)}#107, salary_change{f(EsField)}#108, salary_change.int{f(EsField)}#109, salary_change.keyword{f(KeywordEsField)}#110, salary_change.long{f(EsField)}#111, still_hired{f(EsField)}#112, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#113, x{r}#114, _fork{r}#88, y{r}#115]] + \_Eval[[null[KEYWORD] AS does_not_exist#113, null[DOUBLE] AS x#114]] + \_Eval[[fork2[KEYWORD] AS _fork#88]] + \_Eval[[emp_no{f}#92 + 1[INTEGER] AS y#115]] + \_EsRelation[employees][avg_worked_seconds{f}#90, birth_date{f}#91, emp_no{f}#92, first_name{f}#93, gender{f}#94, height{f}#95, height.float{f}#96, height.half_float{f}#97, height.scaled_float{f}#98, hire_date{f}#99, is_rehired{f}#100, job_positions{f}#101, languages{f}#102, languages.byte{f}#103, languages.long{f}#104, languages.short{f}#105, last_name{f}#106, salary{f}#107, salary_change{f}#108, salary_change.int{f}#109, salary_change.keyword{f}#110, salary_change.long{f}#111, still_hired{f}#112, _score{m}#83, _index{m}#84, _id{m}#85] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql new file mode 100644 index 0000000000000..28caa1c3f1e98 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees METADATA _score, _index, _id +| FORK (EVAL x = does_not_exist::DOUBLE + 1) + (EVAL y = emp_no + 1) +| FUSE RRF diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/analysis.expected new file mode 100644 index 0000000000000..7c2ca4cbcfc17 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/analysis.expected @@ -0,0 +1,17 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(x{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS x#55, VALUES(_fork{r}#56,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#57, VALUES(y{r}#58,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#59]] + \_FuseScoreEval[_score{r}#2,_fork{r}#56,RRF,null] + \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, x{r}#54, _fork{r}#56, y{r}#58]] + |_Limit[1000[INTEGER],false,false] + | \_Project[[avg_worked_seconds{f(EsField)}#60, birth_date{f(DateEsField)}#61, emp_no{f(EsField)}#62, first_name{f(KeywordEsField)}#63, gender{f(KeywordEsField)}#64, height{f(EsField)}#65, height.float{f(EsField)}#66, height.half_float{f(EsField)}#67, height.scaled_float{f(EsField)}#68, hire_date{f(DateEsField)}#69, is_rehired{f(EsField)}#70, job_positions{f(KeywordEsField)}#71, languages{f(EsField)}#72, languages.byte{f(EsField)}#73, languages.long{f(EsField)}#74, languages.short{f(EsField)}#75, last_name{f(KeywordEsField)}#76, salary{f(EsField)}#77, salary_change{f(EsField)}#78, salary_change.int{f(EsField)}#79, salary_change.keyword{f(KeywordEsField)}#80, salary_change.long{f(EsField)}#81, still_hired{f(EsField)}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#86, x{r}#87, _fork{r}#88, y{r}#89]] + | \_Eval[[null[INTEGER] AS y#89]] + | \_Eval[[fork1[KEYWORD] AS _fork#88]] + | \_Eval[[TODOUBLE(does_not_exist{r}#86) + 1[INTEGER] AS x#87]] + | \_Eval[[null[NULL] AS does_not_exist#86]] + | \_EsRelation[employees][avg_worked_seconds{f}#60, birth_date{f}#61, emp_no{f}#62, first_name{f}#63, gender{f}#64, height{f}#65, height.float{f}#66, height.half_float{f}#67, height.scaled_float{f}#68, hire_date{f}#69, is_rehired{f}#70, job_positions{f}#71, languages{f}#72, languages.byte{f}#73, languages.long{f}#74, languages.short{f}#75, last_name{f}#76, salary{f}#77, salary_change{f}#78, salary_change.int{f}#79, salary_change.keyword{f}#80, salary_change.long{f}#81, still_hired{f}#82, _score{m}#83, _index{m}#84, _id{m}#85] + \_Limit[1000[INTEGER],false,false] + \_Project[[avg_worked_seconds{f(EsField)}#90, birth_date{f(DateEsField)}#91, emp_no{f(EsField)}#92, first_name{f(KeywordEsField)}#93, gender{f(KeywordEsField)}#94, height{f(EsField)}#95, height.float{f(EsField)}#96, height.half_float{f(EsField)}#97, height.scaled_float{f(EsField)}#98, hire_date{f(DateEsField)}#99, is_rehired{f(EsField)}#100, job_positions{f(KeywordEsField)}#101, languages{f(EsField)}#102, languages.byte{f(EsField)}#103, languages.long{f(EsField)}#104, languages.short{f(EsField)}#105, last_name{f(KeywordEsField)}#106, salary{f(EsField)}#107, salary_change{f(EsField)}#108, salary_change.int{f(EsField)}#109, salary_change.keyword{f(KeywordEsField)}#110, salary_change.long{f(EsField)}#111, still_hired{f(EsField)}#112, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#113, x{r}#114, _fork{r}#88, y{r}#115]] + \_Eval[[null[NULL] AS does_not_exist#113, null[DOUBLE] AS x#114]] + \_Eval[[fork2[KEYWORD] AS _fork#88]] + \_Eval[[emp_no{f}#92 + 1[INTEGER] AS y#115]] + \_EsRelation[employees][avg_worked_seconds{f}#90, birth_date{f}#91, emp_no{f}#92, first_name{f}#93, gender{f}#94, height{f}#95, height.float{f}#96, height.half_float{f}#97, height.scaled_float{f}#98, hire_date{f}#99, is_rehired{f}#100, job_positions{f}#101, languages{f}#102, languages.byte{f}#103, languages.long{f}#104, languages.short{f}#105, last_name{f}#106, salary{f}#107, salary_change{f}#108, salary_change.int{f}#109, salary_change.keyword{f}#110, salary_change.long{f}#111, still_hired{f}#112, _score{m}#83, _index{m}#84, _id{m}#85] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/query.esql new file mode 100644 index 0000000000000..b4413e66d0853 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees METADATA _score, _index, _id +| FORK (EVAL x = does_not_exist::DOUBLE + 1) + (EVAL y = emp_no + 1) +| FUSE RRF diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected new file mode 100644 index 0000000000000..0507eaa2c2446 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_InlineStats[] + \_Aggregate[[does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0, emp_no{f(EsField)}#1],[SUM(TODOUBLE(does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0, emp_no{f(EsField)}#1]] + \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#1, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26, does_not_exist2{f}#0, does_not_exist1{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/query.esql new file mode 100644 index 0000000000000..8c7146b6bb792 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| INLINE STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected new file mode 100644 index 0000000000000..3d44e8346ff78 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_InlineStats[] + \_Aggregate[[does_not_exist2{r}#0, emp_no{f(EsField)}#1],[SUM(TODOUBLE(does_not_exist1{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{r}#0, emp_no{f(EsField)}#1]] + \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist1#2]] + \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#1, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql new file mode 100644 index 0000000000000..314e176a1843d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| INLINE STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected new file mode 100644 index 0000000000000..2dea9af44b3d1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[x{r}#0]] + \_Eval[[TOVERSION(does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#1) AS x#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/query.esql new file mode 100644 index 0000000000000..4508523015814 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| eval x = does_not_exist_field :: version +| keep x diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/analysis.expected new file mode 100644 index 0000000000000..25f14d02025c3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Project[[x{r}#0]] + \_Eval[[TOVERSION(does_not_exist_field{r}#1) AS x#0]] + \_Eval[[null[NULL] AS does_not_exist_field#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/query.esql new file mode 100644 index 0000000000000..696229a0c3317 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeep/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| eval x = does_not_exist_field :: version +| keep x diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/analysis.expected new file mode 100644 index 0000000000000..31f790943f6fd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{f(EsField)}#0, does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#0, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/query.esql new file mode 100644 index 0000000000000..5c1bb707e111a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| KEEP emp_*, does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/analysis.expected new file mode 100644 index 0000000000000..7b3dd01202d22 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{f(EsField)}#0, does_not_exist_field{r}#1]] + \_Eval[[null[NULL] AS does_not_exist_field#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#0, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/query.esql new file mode 100644 index 0000000000000..0a9ada347fc6a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepAndMatchingStar/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| KEEP emp_*, does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/analysis.expected new file mode 100644 index 0000000000000..d21ff127af792 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/query.esql new file mode 100644 index 0000000000000..ffc9a50988725 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| KEEP does_not_exist_field, does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/analysis.expected new file mode 100644 index 0000000000000..4cc092c3f4aee --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[does_not_exist_field{r}#0]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/query.esql new file mode 100644 index 0000000000000..cef77352827e4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepRepeated/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| KEEP does_not_exist_field, does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected new file mode 100644 index 0000000000000..01fc4148688e2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[42[INTEGER] AS does_not_exist_field#0]] + \_Project[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/query.esql new file mode 100644 index 0000000000000..945f0e290ca38 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| KEEP does_not_exist_field +| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected new file mode 100644 index 0000000000000..f95ae9f74e6dc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[42[INTEGER] AS does_not_exist_field#0]] + \_Project[[does_not_exist_field{r}#1]] + \_Eval[[null[NULL] AS does_not_exist_field#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql new file mode 100644 index 0000000000000..4337b35ba4b2e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| KEEP does_not_exist_field +| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected new file mode 100644 index 0000000000000..92f45cdd558bd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_LookupJoin[LEFT,[language_code{r}#0],[language_code{f(EsField)}#1],false,null] + |_Eval[[TOINTEGER(does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2) AS language_code#0]] + | \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#2] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#1, language_name{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql new file mode 100644 index 0000000000000..45bedb56b16b8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| EVAL language_code = does_not_exist :: INTEGER +| LOOKUP JOIN languages_lookup ON language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/analysis.expected new file mode 100644 index 0000000000000..a6ffe3dba751f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/analysis.expected @@ -0,0 +1,6 @@ +Limit[1000[INTEGER],false,false] +\_LookupJoin[LEFT,[language_code{r}#0],[language_code{f(EsField)}#1],false,null] + |_Eval[[TOINTEGER(does_not_exist{r}#2) AS language_code#0]] + | \_Eval[[null[NULL] AS does_not_exist#2]] + | \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#1, language_name{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/query.esql new file mode 100644 index 0000000000000..a17cbe97c2008 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL language_code = does_not_exist :: INTEGER +| LOOKUP JOIN languages_lookup ON language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected new file mode 100644 index 0000000000000..89dfad1b7ef36 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected @@ -0,0 +1,6 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist{f}#0) > 0[INTEGER]] + \_LookupJoin[LEFT,[language_code{r}#1],[language_code{f(EsField)}#2],false,null] + |_Eval[[languages{f(EsField)}#3 AS language_code#1]] + | \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#3, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#0] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#2, language_name{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql new file mode 100644 index 0000000000000..face9633033a7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees +| EVAL language_code = languages +| LOOKUP JOIN languages_lookup ON language_code +| WHERE does_not_exist::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/analysis.expected new file mode 100644 index 0000000000000..b67ae7d9398f2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/analysis.expected @@ -0,0 +1,7 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist{r}#0) > 0[INTEGER]] + \_LookupJoin[LEFT,[language_code{r}#1],[language_code{f(EsField)}#2],false,null] + |_Eval[[languages{f(EsField)}#3 AS language_code#1, null[NULL] AS does_not_exist#4]] + | \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#7, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#3, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[languages_lookup][LOOKUP][language_code{f}#2, language_name{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/query.esql new file mode 100644 index 0000000000000..891443074f97b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL language_code = languages +| LOOKUP JOIN languages_lookup ON language_code +| WHERE does_not_exist::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/analysis.expected new file mode 100644 index 0000000000000..4074128abfe69 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[message{f(PotentiallyUnmappedKeywordEsField)}#0]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#1, client_ip{f}#2, event_duration{f}#3, message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/query.esql new file mode 100644 index 0000000000000..3b89545a17fb7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, no_mapping_sample_data +| KEEP message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/analysis.expected new file mode 100644 index 0000000000000..b2a87f783ec41 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[message{f(KeywordEsField)}#0]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#1, client_ip{f}#2, event_duration{f}#3, message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/query.esql new file mode 100644 index 0000000000000..9ab256bac0ccc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnly/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, no_mapping_sample_data +| KEEP message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/analysis.expected new file mode 100644 index 0000000000000..9ec2b3b4a4afd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TOLONG(message{f(PotentiallyUnmappedKeywordEsField)}#0) AS x#1]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/query.esql new file mode 100644 index 0000000000000..5f15147e4ed84 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, no_mapping_sample_data +| EVAL x = message :: LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/analysis.expected new file mode 100644 index 0000000000000..199057917fbe8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TOLONG(message{f(KeywordEsField)}#0) AS x#1]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/query.esql new file mode 100644 index 0000000000000..46601c5b712ed --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedInOneIndexOnlyCast/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, no_mapping_sample_data +| EVAL x = message :: LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/analysis.expected new file mode 100644 index 0000000000000..812e7c610bd25 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[!event_duration]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#0, client_ip{f}#1, event_duration{f}#2, message{f}#3] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/query.esql new file mode 100644 index 0000000000000..2d32247edd0a4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, no_mapping_sample_data +| KEEP event_duration diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/analysis.expected new file mode 100644 index 0000000000000..c417694e5f80d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[event_duration{f(EsField)}#0]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#1, client_ip{f}#2, event_duration{f}#0, message{f}#3] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/query.esql new file mode 100644 index 0000000000000..dac9f41556304 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnly/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, no_mapping_sample_data +| KEEP event_duration diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql new file mode 100644 index 0000000000000..75ac5ca4e241d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, no_mapping_sample_data +| EVAL x = event_duration :: DOUBLE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/load/analysis.expected new file mode 100644 index 0000000000000..9b8968ae63fd7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/load/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(b{f}#0) + TODOUBLE(c{f}#1) AS y#2]] + \_Eval[[a{r}#3 + TODOUBLE(b{f}#0) AS x#4]] + \_Eval[[1[INTEGER] AS a#3]] + \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#7, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27, b{f}#0, c{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/load/query.esql new file mode 100644 index 0000000000000..78c3271ba9d3c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/load/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="load"; FROM employees +| EVAL a = 1 +| EVAL x = a + b::DOUBLE +| EVAL y = b::DOUBLE + c::DOUBLE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/analysis.expected new file mode 100644 index 0000000000000..db17e201ae307 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(b{r}#0) + TODOUBLE(c{r}#1) AS y#2]] + \_Eval[[a{r}#3 + TODOUBLE(b{r}#0) AS x#4]] + \_Eval[[1[INTEGER] AS a#3, null[NULL] AS b#0, null[NULL] AS c#1]] + \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#7, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/query.esql new file mode 100644 index 0000000000000..1c122d2bc9737 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMultipleEval/nullify/query.esql @@ -0,0 +1,4 @@ +SET unmapped_fields="nullify"; FROM employees +| EVAL a = 1 +| EVAL x = a + b::DOUBLE +| EVAL y = b::DOUBLE + c::DOUBLE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/analysis.expected new file mode 100644 index 0000000000000..16c852fe171c6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_MvExpand[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#0,does_not_exist{r}#1] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/query.esql new file mode 100644 index 0000000000000..470cc59438c6c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| MV_EXPAND does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/analysis.expected new file mode 100644 index 0000000000000..2720ef7cf3a24 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_MvExpand[does_not_exist{r}#0,does_not_exist{r}#1] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/query.esql new file mode 100644 index 0000000000000..4028dd22bad3d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMvExpand/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| MV_EXPAND does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/analysis.expected new file mode 100644 index 0000000000000..6491d2ecb54e7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[@timestamp{f(DateEsField)}#0, message{f(KeywordEsField)}#1, unmapped_message{f(PotentiallyUnmappedKeywordEsField)}#2]] + \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#3, event_duration{f}#4, message{f}#1, unmapped_message{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/query.esql new file mode 100644 index 0000000000000..84d4cfd6038b2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data, partial_mapping_sample_data +| KEEP @timestamp, message, unmapped_message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/analysis.expected new file mode 100644 index 0000000000000..b637cc104c27c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[@timestamp{f(DateEsField)}#0, message{f(KeywordEsField)}#1, unmapped_message{r}#2]] + \_Eval[[null[NULL] AS unmapped_message#2]] + \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#3, event_duration{f}#4, message{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/query.esql new file mode 100644 index 0000000000000..f685cd7d68cda --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedField/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data, partial_mapping_sample_data +| KEEP @timestamp, message, unmapped_message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/analysis.expected new file mode 100644 index 0000000000000..fc6e42d4dce53 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2 AS employee_number#3, first_name{f(KeywordEsField)}#4, gender{f(KeywordEsField)}#5, height{f(EsField)}#6, height.float{f(EsField)}#7, height.half_float{f(EsField)}#8, height.scaled_float{f(EsField)}#9, hire_date{f(DateEsField)}#10, is_rehired{f(EsField)}#11, job_positions{f(KeywordEsField)}#12, languages{f(EsField)}#13, languages.byte{f(EsField)}#14, languages.long{f(EsField)}#15, languages.short{f(EsField)}#16, last_name{f(KeywordEsField)}#17, salary{f(EsField)}#18, salary_change{f(EsField)}#19, salary_change.int{f(EsField)}#20, salary_change.keyword{f(KeywordEsField)}#21, salary_change.long{f(EsField)}#22, still_hired{f(EsField)}#23, does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#24 AS now_it_does#25]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/query.esql new file mode 100644 index 0000000000000..319f90371ed9c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| RENAME does_not_exist_field AS now_it_does, emp_no AS employee_number diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/analysis.expected new file mode 100644 index 0000000000000..f0e2cc4908423 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2 AS employee_number#3, first_name{f(KeywordEsField)}#4, gender{f(KeywordEsField)}#5, height{f(EsField)}#6, height.float{f(EsField)}#7, height.half_float{f(EsField)}#8, height.scaled_float{f(EsField)}#9, hire_date{f(DateEsField)}#10, is_rehired{f(EsField)}#11, job_positions{f(KeywordEsField)}#12, languages{f(EsField)}#13, languages.byte{f(EsField)}#14, languages.long{f(EsField)}#15, languages.short{f(EsField)}#16, last_name{f(KeywordEsField)}#17, salary{f(EsField)}#18, salary_change{f(EsField)}#19, salary_change.int{f(EsField)}#20, salary_change.keyword{f(KeywordEsField)}#21, salary_change.long{f(EsField)}#22, still_hired{f(EsField)}#23, does_not_exist_field{r}#24 AS now_it_does#25]] + \_Eval[[null[NULL] AS does_not_exist_field#24]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/query.esql new file mode 100644 index 0000000000000..5b99834da2a5a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRename/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| RENAME does_not_exist_field AS now_it_does, emp_no AS employee_number diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected new file mode 100644 index 0000000000000..c31cede9fea9b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(does_not_exist{f}#0) + 1[INTEGER] AS x#1]] + \_Project[[avg_worked_seconds{f(EsField)}#2, birth_date{f(DateEsField)}#3, emp_no{f(EsField)}#4 AS employee_number#5, first_name{f(KeywordEsField)}#6, gender{f(KeywordEsField)}#7, height{f(EsField)}#8, height.float{f(EsField)}#9, height.half_float{f(EsField)}#10, height.scaled_float{f(EsField)}#11, hire_date{f(DateEsField)}#12, is_rehired{f(EsField)}#13, job_positions{f(KeywordEsField)}#14, languages{f(EsField)}#15, languages.byte{f(EsField)}#16, languages.long{f(EsField)}#17, languages.short{f(EsField)}#18, last_name{f(KeywordEsField)}#19, salary{f(EsField)}#20, salary_change{f(EsField)}#21, salary_change.int{f(EsField)}#22, salary_change.keyword{f(KeywordEsField)}#23, salary_change.long{f(EsField)}#24, still_hired{f(EsField)}#25, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/query.esql new file mode 100644 index 0000000000000..15a3d0131d523 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| RENAME emp_no AS employee_number +| EVAL x = does_not_exist::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected new file mode 100644 index 0000000000000..1ead97977e5fb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected @@ -0,0 +1,5 @@ +Limit[1000[INTEGER],false,false] +\_Eval[[TODOUBLE(does_not_exist{r}#0) + 1[INTEGER] AS x#1]] + \_Project[[avg_worked_seconds{f(EsField)}#2, birth_date{f(DateEsField)}#3, emp_no{f(EsField)}#4 AS employee_number#5, first_name{f(KeywordEsField)}#6, gender{f(KeywordEsField)}#7, height{f(EsField)}#8, height.float{f(EsField)}#9, height.half_float{f(EsField)}#10, height.scaled_float{f(EsField)}#11, hire_date{f(DateEsField)}#12, is_rehired{f(EsField)}#13, job_positions{f(KeywordEsField)}#14, languages{f(EsField)}#15, languages.byte{f(EsField)}#16, languages.long{f(EsField)}#17, languages.short{f(EsField)}#18, last_name{f(KeywordEsField)}#19, salary{f(EsField)}#20, salary_change{f(EsField)}#21, salary_change.int{f(EsField)}#22, salary_change.keyword{f(KeywordEsField)}#23, salary_change.long{f(EsField)}#24, still_hired{f(EsField)}#25, does_not_exist{r}#0]] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql new file mode 100644 index 0000000000000..7475a95153a3a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| RENAME emp_no AS employee_number +| EVAL x = does_not_exist::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected new file mode 100644 index 0000000000000..41a803dee2b34 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2 AS employee_number#3, first_name{f(KeywordEsField)}#4, gender{f(KeywordEsField)}#5, height{f(EsField)}#6, height.float{f(EsField)}#7, height.half_float{f(EsField)}#8, height.scaled_float{f(EsField)}#9, hire_date{f(DateEsField)}#10, is_rehired{f(EsField)}#11, job_positions{f(KeywordEsField)}#12, languages{f(EsField)}#13, languages.byte{f(EsField)}#14, languages.long{f(EsField)}#15, languages.short{f(EsField)}#16, last_name{f(KeywordEsField)}#17, salary{f(EsField)}#18, salary_change{f(EsField)}#19, salary_change.int{f(EsField)}#20, salary_change.keyword{f(KeywordEsField)}#21, salary_change.long{f(EsField)}#22, still_hired{f(EsField)}#23, neither_does_this{f(PotentiallyUnmappedKeywordEsField)}#24 AS now_it_does#25]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#26, neither_does_this{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/query.esql new file mode 100644 index 0000000000000..efad9ee315214 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| RENAME does_not_exist_field AS now_it_does, neither_does_this AS now_it_does, emp_no AS employee_number diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected new file mode 100644 index 0000000000000..f828b3f7c9f30 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2 AS employee_number#3, first_name{f(KeywordEsField)}#4, gender{f(KeywordEsField)}#5, height{f(EsField)}#6, height.float{f(EsField)}#7, height.half_float{f(EsField)}#8, height.scaled_float{f(EsField)}#9, hire_date{f(DateEsField)}#10, is_rehired{f(EsField)}#11, job_positions{f(KeywordEsField)}#12, languages{f(EsField)}#13, languages.byte{f(EsField)}#14, languages.long{f(EsField)}#15, languages.short{f(EsField)}#16, last_name{f(KeywordEsField)}#17, salary{f(EsField)}#18, salary_change{f(EsField)}#19, salary_change.int{f(EsField)}#20, salary_change.keyword{f(KeywordEsField)}#21, salary_change.long{f(EsField)}#22, still_hired{f(EsField)}#23, neither_does_this{r}#24 AS now_it_does#25]] + \_Eval[[null[NULL] AS does_not_exist_field#26, null[NULL] AS neither_does_this#24]] + \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/query.esql new file mode 100644 index 0000000000000..db1febeb315ad --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| RENAME does_not_exist_field AS now_it_does, neither_does_this AS now_it_does, emp_no AS employee_number diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/analysis.expected new file mode 100644 index 0000000000000..fd2ab06e624be --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#0,ASC,LAST]]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/query.esql new file mode 100644 index 0000000000000..6f307e4be48c6 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| SORT does_not_exist ASC diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/analysis.expected new file mode 100644 index 0000000000000..df3459bd98905 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[does_not_exist{r}#0,ASC,LAST]]] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/query.esql new file mode 100644 index 0000000000000..e2e03a32e90b3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSort/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| SORT does_not_exist ASC diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/load/analysis.expected new file mode 100644 index 0000000000000..194c11cb2dd74 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[TOLONG(does_not_exist{f}#0) + 1[INTEGER],ASC,LAST]]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/load/query.esql new file mode 100644 index 0000000000000..0f20bd09a4191 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| SORT does_not_exist::LONG + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/analysis.expected new file mode 100644 index 0000000000000..09bb15a967666 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[TOLONG(does_not_exist{r}#0) + 1[INTEGER],ASC,LAST]]] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/query.esql new file mode 100644 index 0000000000000..4f3e51522c415 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortExpression/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| SORT does_not_exist::LONG + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected new file mode 100644 index 0000000000000..b6e10e3bc15c1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[TOLONG(does_not_exist1{f}#0) + 1[INTEGER],ASC,LAST], Order[does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#1,DESC,FIRST], Order[emp_no{f(EsField)}#2,ASC,LAST]]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist1{f}#0, does_not_exist2{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/query.esql new file mode 100644 index 0000000000000..df129647e7c8a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| SORT does_not_exist1::LONG + 1, does_not_exist2 DESC, emp_no ASC diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected new file mode 100644 index 0000000000000..272402c1c32eb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_OrderBy[[Order[TOLONG(does_not_exist1{r}#0) + 1[INTEGER],ASC,LAST], Order[does_not_exist2{r}#1,DESC,FIRST], Order[emp_no{f(EsField)}#2,ASC,LAST]]] + \_Eval[[null[NULL] AS does_not_exist1#0, null[NULL] AS does_not_exist2#1]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/query.esql new file mode 100644 index 0000000000000..7b1dadb3f7ed2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| SORT does_not_exist1::LONG + 1, does_not_exist2 DESC, emp_no ASC diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected new file mode 100644 index 0000000000000..72036927b0717 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0],[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/query.esql new file mode 100644 index 0000000000000..d13f24be60435 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS BY does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/analysis.expected new file mode 100644 index 0000000000000..dc5330d4bd4ae --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[does_not_exist_field{r}#0],[does_not_exist_field{r}#0]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/query.esql new file mode 100644 index 0000000000000..b4ef8dbc01160 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS BY does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected new file mode 100644 index 0000000000000..4266a433ba529 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[],[COUNT(does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/query.esql new file mode 100644 index 0000000000000..2e1086f20474e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS cnt = COUNT(does_not_exist_field) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/analysis.expected new file mode 100644 index 0000000000000..bce83c7e94ff2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[],[COUNT(does_not_exist_field{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt#1]] + \_Eval[[null[NULL] AS does_not_exist_field#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/query.esql new file mode 100644 index 0000000000000..e8fb3888650cf --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS cnt = COUNT(does_not_exist_field) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/analysis.expected new file mode 100644 index 0000000000000..0e4402c48cdba --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{f}#0) > 0[INTEGER]] AS c#1]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist1{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/query.esql new file mode 100644 index 0000000000000..c761b990a28aa --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/analysis.expected new file mode 100644 index 0000000000000..31ed40e729ba7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{r}#0) > 0[INTEGER]] AS c#1]] + \_Eval[[null[NULL] AS does_not_exist1#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/query.esql new file mode 100644 index 0000000000000..7c028cc985242 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected new file mode 100644 index 0000000000000..20e247409cc03 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0, emp_no{f(EsField)}#1],[SUM(TODOUBLE(does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0, emp_no{f(EsField)}#1]] + \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#1, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26, does_not_exist2{f}#0, does_not_exist1{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/query.esql new file mode 100644 index 0000000000000..ecc9a01cd10d1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected new file mode 100644 index 0000000000000..4e82f82142c41 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[does_not_exist2{r}#0, emp_no{f(EsField)}#1],[SUM(TODOUBLE(does_not_exist1{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{r}#0, emp_no{f(EsField)}#1]] + \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist1#2]] + \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#1, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/query.esql new file mode 100644 index 0000000000000..6887849dbdcd4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected new file mode 100644 index 0000000000000..de76cbb9a017a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{f}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER] OR TOLONG(does_not_exist2{f}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{f(PotentiallyUnmappedKeywordEsField)}#4)] AS c2#5]] + \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#1, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27, does_not_exist1{f}#0, does_not_exist2{f}#2, does_not_exist3{f}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/query.esql new file mode 100644 index 0000000000000..3078319477f7f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees +| STATS c1 = COUNT(*) WHERE does_not_exist1::LONG > 0 OR emp_no > 0 OR does_not_exist2::LONG < 100, + c2 = COUNT(*) WHERE does_not_exist3 IS NULL diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected new file mode 100644 index 0000000000000..6f8fec253f83b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{r}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER] OR TOLONG(does_not_exist2{r}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{r}#4)] AS c2#5]] + \_Eval[[null[NULL] AS does_not_exist1#0, null[NULL] AS does_not_exist2#2, null[NULL] AS does_not_exist3#4]] + \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#1, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/query.esql new file mode 100644 index 0000000000000..6f052b1a79cb2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS c1 = COUNT(*) WHERE does_not_exist1::LONG > 0 OR emp_no > 0 OR does_not_exist2::LONG < 100, + c2 = COUNT(*) WHERE does_not_exist3 IS NULL diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected new file mode 100644 index 0000000000000..3da6706296c63 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0],[SUM(TODOUBLE(does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#1),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#2, does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist2{f}#0, does_not_exist1{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/query.esql new file mode 100644 index 0000000000000..4b45cf86d8cb5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/analysis.expected new file mode 100644 index 0000000000000..75f108928c116 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[does_not_exist2{r}#0],[SUM(TODOUBLE(does_not_exist1{r}#1),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#2, does_not_exist2{r}#0]] + \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist1#1]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/query.esql new file mode 100644 index 0000000000000..29d53f6beba5b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected new file mode 100644 index 0000000000000..f8c89887de2f8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TODOUBLE(does_not_exist2{f}#0) + TODOUBLE(does_not_exist3{f}#1) AS s0#2, emp_no{f(EsField)}#3 AS s1#4],[SUM(TODOUBLE(does_not_exist1{f}#5),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + s0{r}#2 + s1{r}#4 AS sum#6, s0{r}#2, s1{r}#4]] + \_EsRelation[employees][avg_worked_seconds{f}#7, birth_date{f}#8, emp_no{f}#3, first_name{f}#9, gender{f}#10, height{f}#11, height.float{f}#12, height.half_float{f}#13, height.scaled_float{f}#14, hire_date{f}#15, is_rehired{f}#16, job_positions{f}#17, languages{f}#18, languages.byte{f}#19, languages.long{f}#20, languages.short{f}#21, last_name{f}#22, salary{f}#23, salary_change{f}#24, salary_change.int{f}#25, salary_change.keyword{f}#26, salary_change.long{f}#27, still_hired{f}#28, does_not_exist2{f}#0, does_not_exist3{f}#1, does_not_exist1{f}#5, s0{f}#29] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/query.esql new file mode 100644 index 0000000000000..c8ed9b159cb2a --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS sum = SUM(does_not_exist1::DOUBLE) + s0 + s1 BY s0 = does_not_exist2::DOUBLE + does_not_exist3::DOUBLE, s1 = emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected new file mode 100644 index 0000000000000..f324c6cc494bb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TODOUBLE(does_not_exist2{r}#0) + TODOUBLE(does_not_exist3{r}#1) AS s0#2, emp_no{f(EsField)}#3 AS s1#4],[SUM(TODOUBLE(does_not_exist1{r}#5),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + s0{r}#2 + s1{r}#4 AS sum#6, s0{r}#2, s1{r}#4]] + \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist3#1, null[NULL] AS does_not_exist1#5, null[NULL] AS s0#7]] + \_EsRelation[employees][avg_worked_seconds{f}#8, birth_date{f}#9, emp_no{f}#3, first_name{f}#10, gender{f}#11, height{f}#12, height.float{f}#13, height.half_float{f}#14, height.scaled_float{f}#15, hire_date{f}#16, is_rehired{f}#17, job_positions{f}#18, languages{f}#19, languages.byte{f}#20, languages.long{f}#21, languages.short{f}#22, last_name{f}#23, salary{f}#24, salary_change{f}#25, salary_change.int{f}#26, salary_change.keyword{f}#27, salary_change.long{f}#28, still_hired{f}#29] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/query.esql new file mode 100644 index 0000000000000..d4152fb7a5e2f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS sum = SUM(does_not_exist1::DOUBLE) + s0 + s1 BY s0 = does_not_exist2::DOUBLE + does_not_exist3::DOUBLE, s1 = emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected new file mode 100644 index 0000000000000..441d733d2e22d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TODOUBLE(does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0) AS d2#1, emp_no{f(EsField)}#2],[SUM(TODOUBLE(does_not_exist1{f}#3),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + d2{r}#1 AS s#4, d2{r}#1, emp_no{f(EsField)}#2]] + \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#2, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26, does_not_exist2{f}#0, does_not_exist1{f}#3, d2{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/query.esql new file mode 100644 index 0000000000000..d548e72eda5de --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| STATS s = SUM(does_not_exist1::DOUBLE) + d2 BY d2 = does_not_exist2::DOUBLE, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected new file mode 100644 index 0000000000000..bcfbad0e4899c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TODOUBLE(does_not_exist2{r}#0) AS d2#1, emp_no{f(EsField)}#2],[SUM(TODOUBLE(does_not_exist1{r}#3),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + d2{r}#1 AS s#4, d2{r}#1, emp_no{f(EsField)}#2]] + \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist1#3, null[NULL] AS d2#5]] + \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#2, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/query.esql new file mode 100644 index 0000000000000..c9f8f55bbee50 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| STATS s = SUM(does_not_exist1::DOUBLE) + d2 BY d2 = does_not_exist2::DOUBLE, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..5c3d84282236b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected @@ -0,0 +1,11 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] + \_UnionAll[[avg_worked_seconds{r}#4, birth_date{r}#5, emp_no{r}#0, first_name{r}#6, gender{r}#7, height{r}#8, height.float{r}#9, height.half_float{r}#10, height.scaled_float{r}#11, hire_date{r}#12, is_rehired{r}#13, job_positions{r}#14, languages{r}#15, languages.byte{r}#16, languages.long{r}#17, languages.short{r}#18, last_name{r}#19, salary{r}#20, salary_change{r}#21, salary_change.int{r}#22, salary_change.keyword{r}#23, salary_change.long{r}#24, still_hired{r}#25, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] + |_Project[[avg_worked_seconds{f(EsField)}#26, birth_date{f(DateEsField)}#27, emp_no{f(EsField)}#28, first_name{f(KeywordEsField)}#29, gender{f(KeywordEsField)}#30, height{f(EsField)}#31, height.float{f(EsField)}#32, height.half_float{f(EsField)}#33, height.scaled_float{f(EsField)}#34, hire_date{f(DateEsField)}#35, is_rehired{f(EsField)}#36, job_positions{f(KeywordEsField)}#37, languages{f(EsField)}#38, languages.byte{f(EsField)}#39, languages.long{f(EsField)}#40, languages.short{f(EsField)}#41, last_name{f(KeywordEsField)}#42, salary{f(EsField)}#43, salary_change{f(EsField)}#44, salary_change.int{f(EsField)}#45, salary_change.keyword{f(KeywordEsField)}#46, salary_change.long{f(EsField)}#47, still_hired{f(EsField)}#48, language_code{r}#49, unmapped1{r}#50, unmapped2{r}#51]] + | \_Eval[[null[INTEGER] AS language_code#49, null[KEYWORD] AS unmapped1#50, null[KEYWORD] AS unmapped2#51]] + | \_EsRelation[employees][avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48] + \_Project[[avg_worked_seconds{r}#52, birth_date{r}#53, emp_no{r}#54, first_name{r}#55, gender{r}#56, height{r}#57, height.float{r}#58, height.half_float{r}#59, height.scaled_float{r}#60, hire_date{r}#61, is_rehired{r}#62, job_positions{r}#63, languages{r}#64, languages.byte{r}#65, languages.long{r}#66, languages.short{r}#67, last_name{r}#68, salary{r}#69, salary_change{r}#70, salary_change.int{r}#71, salary_change.keyword{r}#72, salary_change.long{r}#73, still_hired{r}#74, language_code{f(EsField)}#75, unmapped1{f(PotentiallyUnmappedKeywordEsField)}#76, unmapped2{f(PotentiallyUnmappedKeywordEsField)}#77]] + \_Eval[[null[LONG] AS avg_worked_seconds#52, null[DATETIME] AS birth_date#53, null[INTEGER] AS emp_no#54, null[KEYWORD] AS first_name#55, null[KEYWORD] AS gender#56, null[DOUBLE] AS height#57, null[DOUBLE] AS height.float#58, null[DOUBLE] AS height.half_float#59, null[DOUBLE] AS height.scaled_float#60, null[DATETIME] AS hire_date#61, null[BOOLEAN] AS is_rehired#62, null[KEYWORD] AS job_positions#63, null[INTEGER] AS languages#64, null[INTEGER] AS languages.byte#65, null[LONG] AS languages.long#66, null[INTEGER] AS languages.short#67, null[KEYWORD] AS last_name#68, null[INTEGER] AS salary#69, null[DOUBLE] AS salary_change#70, null[INTEGER] AS salary_change.int#71, null[KEYWORD] AS salary_change.keyword#72, null[LONG] AS salary_change.long#73, null[BOOLEAN] AS still_hired#74]] + \_Subquery[] + \_Project[[language_code{f(EsField)}#75, unmapped1{f(PotentiallyUnmappedKeywordEsField)}#76, unmapped2{f(PotentiallyUnmappedKeywordEsField)}#77]] + \_EsRelation[languages][language_code{f}#75, language_name{f}#78, unmapped1{f}#76, unmapped2{f}#77] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql new file mode 100644 index 0000000000000..f48daedc4ab1d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM employees, + (FROM languages | KEEP language_code, unmapped1, unmapped2) +| KEEP emp_no, language_code, unmapped1, unmapped2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..12cb504aaa345 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/analysis.expected @@ -0,0 +1,12 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] + \_UnionAll[[avg_worked_seconds{r}#4, birth_date{r}#5, emp_no{r}#0, first_name{r}#6, gender{r}#7, height{r}#8, height.float{r}#9, height.half_float{r}#10, height.scaled_float{r}#11, hire_date{r}#12, is_rehired{r}#13, job_positions{r}#14, languages{r}#15, languages.byte{r}#16, languages.long{r}#17, languages.short{r}#18, last_name{r}#19, salary{r}#20, salary_change{r}#21, salary_change.int{r}#22, salary_change.keyword{r}#23, salary_change.long{r}#24, still_hired{r}#25, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] + |_Project[[avg_worked_seconds{f(EsField)}#26, birth_date{f(DateEsField)}#27, emp_no{f(EsField)}#28, first_name{f(KeywordEsField)}#29, gender{f(KeywordEsField)}#30, height{f(EsField)}#31, height.float{f(EsField)}#32, height.half_float{f(EsField)}#33, height.scaled_float{f(EsField)}#34, hire_date{f(DateEsField)}#35, is_rehired{f(EsField)}#36, job_positions{f(KeywordEsField)}#37, languages{f(EsField)}#38, languages.byte{f(EsField)}#39, languages.long{f(EsField)}#40, languages.short{f(EsField)}#41, last_name{f(KeywordEsField)}#42, salary{f(EsField)}#43, salary_change{f(EsField)}#44, salary_change.int{f(EsField)}#45, salary_change.keyword{f(KeywordEsField)}#46, salary_change.long{f(EsField)}#47, still_hired{f(EsField)}#48, language_code{r}#49, unmapped1{r}#50, unmapped2{r}#51]] + | \_Eval[[null[INTEGER] AS language_code#49, null[NULL] AS unmapped1#50, null[NULL] AS unmapped2#51]] + | \_EsRelation[employees][avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48] + \_Project[[avg_worked_seconds{r}#52, birth_date{r}#53, emp_no{r}#54, first_name{r}#55, gender{r}#56, height{r}#57, height.float{r}#58, height.half_float{r}#59, height.scaled_float{r}#60, hire_date{r}#61, is_rehired{r}#62, job_positions{r}#63, languages{r}#64, languages.byte{r}#65, languages.long{r}#66, languages.short{r}#67, last_name{r}#68, salary{r}#69, salary_change{r}#70, salary_change.int{r}#71, salary_change.keyword{r}#72, salary_change.long{r}#73, still_hired{r}#74, language_code{f(EsField)}#75, unmapped1{r}#76, unmapped2{r}#77]] + \_Eval[[null[LONG] AS avg_worked_seconds#52, null[DATETIME] AS birth_date#53, null[INTEGER] AS emp_no#54, null[KEYWORD] AS first_name#55, null[KEYWORD] AS gender#56, null[DOUBLE] AS height#57, null[DOUBLE] AS height.float#58, null[DOUBLE] AS height.half_float#59, null[DOUBLE] AS height.scaled_float#60, null[DATETIME] AS hire_date#61, null[BOOLEAN] AS is_rehired#62, null[KEYWORD] AS job_positions#63, null[INTEGER] AS languages#64, null[INTEGER] AS languages.byte#65, null[LONG] AS languages.long#66, null[INTEGER] AS languages.short#67, null[KEYWORD] AS last_name#68, null[INTEGER] AS salary#69, null[DOUBLE] AS salary_change#70, null[INTEGER] AS salary_change.int#71, null[KEYWORD] AS salary_change.keyword#72, null[LONG] AS salary_change.long#73, null[BOOLEAN] AS still_hired#74]] + \_Subquery[] + \_Project[[language_code{f(EsField)}#75, unmapped1{r}#76, unmapped2{r}#77]] + \_Eval[[null[NULL] AS unmapped1#76, null[NULL] AS unmapped2#77]] + \_EsRelation[languages][language_code{f}#75, language_name{f}#78] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..eed7eb85db071 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM employees, + (FROM languages | KEEP language_code, unmapped1, unmapped2) +| KEEP emp_no, language_code, unmapped1, unmapped2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..cc9006fedeefc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected @@ -0,0 +1,13 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, language_code{r}#1, does_not_exist{r}#2]] + \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, language_code{r}#1, does_not_exist{r}#2]] + |_Project[[avg_worked_seconds{f(EsField)}#25, birth_date{f(DateEsField)}#26, emp_no{f(EsField)}#27, first_name{f(KeywordEsField)}#28, gender{f(KeywordEsField)}#29, height{f(EsField)}#30, height.float{f(EsField)}#31, height.half_float{f(EsField)}#32, height.scaled_float{f(EsField)}#33, hire_date{f(DateEsField)}#34, is_rehired{f(EsField)}#35, job_positions{f(KeywordEsField)}#36, languages{f(EsField)}#37, languages.byte{f(EsField)}#38, languages.long{f(EsField)}#39, languages.short{f(EsField)}#40, last_name{f(KeywordEsField)}#41, salary{f(EsField)}#42, salary_change{f(EsField)}#43, salary_change.int{f(EsField)}#44, salary_change.keyword{f(KeywordEsField)}#45, salary_change.long{f(EsField)}#46, still_hired{f(EsField)}#47, language_code{r}#48, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#49]] + | \_Eval[[null[INTEGER] AS language_code#48]] + | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, does_not_exist{f}#49] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f(EsField)}#73, does_not_exist{r}#74]] + \_Eval[[null[KEYWORD] AS does_not_exist#74]] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f(EsField)}#73]] + \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] + \_Subquery[] + \_Project[[language_code{f(EsField)}#73]] + \_EsRelation[languages][language_code{f}#73, language_name{f}#75, does_not_exist{f}#76] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql new file mode 100644 index 0000000000000..1b76ece4d7ba5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees, (FROM languages | KEEP language_code) +| KEEP emp_no, language_code, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..5d191d8cee373 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/analysis.expected @@ -0,0 +1,14 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, language_code{r}#1, does_not_exist{r}#2]] + \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, language_code{r}#1, does_not_exist{r}#2]] + |_Project[[avg_worked_seconds{f(EsField)}#25, birth_date{f(DateEsField)}#26, emp_no{f(EsField)}#27, first_name{f(KeywordEsField)}#28, gender{f(KeywordEsField)}#29, height{f(EsField)}#30, height.float{f(EsField)}#31, height.half_float{f(EsField)}#32, height.scaled_float{f(EsField)}#33, hire_date{f(DateEsField)}#34, is_rehired{f(EsField)}#35, job_positions{f(KeywordEsField)}#36, languages{f(EsField)}#37, languages.byte{f(EsField)}#38, languages.long{f(EsField)}#39, languages.short{f(EsField)}#40, last_name{f(KeywordEsField)}#41, salary{f(EsField)}#42, salary_change{f(EsField)}#43, salary_change.int{f(EsField)}#44, salary_change.keyword{f(KeywordEsField)}#45, salary_change.long{f(EsField)}#46, still_hired{f(EsField)}#47, language_code{r}#48, does_not_exist{r}#49]] + | \_Eval[[null[INTEGER] AS language_code#48, null[NULL] AS does_not_exist#49]] + | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f(EsField)}#73, does_not_exist{r}#74]] + \_Eval[[null[NULL] AS does_not_exist#74]] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f(EsField)}#73]] + \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] + \_Subquery[] + \_Project[[language_code{f(EsField)}#73]] + \_Eval[[null[NULL] AS does_not_exist#75]] + \_EsRelation[languages][language_code{f}#73, language_name{f}#76] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..b1c83359017cb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees, (FROM languages | KEEP language_code) +| KEEP emp_no, language_code, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected new file mode 100644 index 0000000000000..d7d41100c00dc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected @@ -0,0 +1,11 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, max_ts{r}#1, does_not_exist{r}#2]] + \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, max_ts{r}#1, does_not_exist{r}#2]] + |_Project[[avg_worked_seconds{f(EsField)}#25, birth_date{f(DateEsField)}#26, emp_no{f(EsField)}#27, first_name{f(KeywordEsField)}#28, gender{f(KeywordEsField)}#29, height{f(EsField)}#30, height.float{f(EsField)}#31, height.half_float{f(EsField)}#32, height.scaled_float{f(EsField)}#33, hire_date{f(DateEsField)}#34, is_rehired{f(EsField)}#35, job_positions{f(KeywordEsField)}#36, languages{f(EsField)}#37, languages.byte{f(EsField)}#38, languages.long{f(EsField)}#39, languages.short{f(EsField)}#40, last_name{f(KeywordEsField)}#41, salary{f(EsField)}#42, salary_change{f(EsField)}#43, salary_change.int{f(EsField)}#44, salary_change.keyword{f(KeywordEsField)}#45, salary_change.long{f(EsField)}#46, still_hired{f(EsField)}#47, max_ts{r}#48, does_not_exist{r}#49]] + | \_Eval[[null[DATETIME] AS max_ts#48, null[KEYWORD] AS does_not_exist#49]] + | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, max_ts{r}#73, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74]] + \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] + \_Subquery[] + \_Aggregate[[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74],[MAX(@timestamp{f(DateEsField)}#75,true[BOOLEAN],PT0S[TIME_DURATION]) AS max_ts#73, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74]] + \_EsRelation[sample_data][@timestamp{f}#75, client_ip{f}#76, event_duration{f}#77, message{f}#78, does_not_exist{f}#74] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql new file mode 100644 index 0000000000000..dabf6fc1b0e8c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees, (FROM sample_data | STATS max_ts = MAX(@timestamp) BY does_not_exist) +| KEEP emp_no, max_ts, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/analysis.expected new file mode 100644 index 0000000000000..45949bb3dc895 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/analysis.expected @@ -0,0 +1,12 @@ +Limit[1000[INTEGER],false,false] +\_Project[[emp_no{r}#0, max_ts{r}#1, does_not_exist{r}#2]] + \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, max_ts{r}#1, does_not_exist{r}#2]] + |_Project[[avg_worked_seconds{f(EsField)}#25, birth_date{f(DateEsField)}#26, emp_no{f(EsField)}#27, first_name{f(KeywordEsField)}#28, gender{f(KeywordEsField)}#29, height{f(EsField)}#30, height.float{f(EsField)}#31, height.half_float{f(EsField)}#32, height.scaled_float{f(EsField)}#33, hire_date{f(DateEsField)}#34, is_rehired{f(EsField)}#35, job_positions{f(KeywordEsField)}#36, languages{f(EsField)}#37, languages.byte{f(EsField)}#38, languages.long{f(EsField)}#39, languages.short{f(EsField)}#40, last_name{f(KeywordEsField)}#41, salary{f(EsField)}#42, salary_change{f(EsField)}#43, salary_change.int{f(EsField)}#44, salary_change.keyword{f(KeywordEsField)}#45, salary_change.long{f(EsField)}#46, still_hired{f(EsField)}#47, max_ts{r}#48, does_not_exist{r}#49]] + | \_Eval[[null[DATETIME] AS max_ts#48, null[NULL] AS does_not_exist#49]] + | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] + \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, max_ts{r}#73, does_not_exist{r}#74]] + \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] + \_Subquery[] + \_Aggregate[[does_not_exist{r}#74],[MAX(@timestamp{f(DateEsField)}#75,true[BOOLEAN],PT0S[TIME_DURATION]) AS max_ts#73, does_not_exist{r}#74]] + \_Eval[[null[NULL] AS does_not_exist#74]] + \_EsRelation[sample_data][@timestamp{f}#75, client_ip{f}#76, event_duration{f}#77, message{f}#78] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/query.esql new file mode 100644 index 0000000000000..7c5a4d44bddb0 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees, (FROM sample_data | STATS max_ts = MAX(@timestamp) BY does_not_exist) +| KEEP emp_no, max_ts, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..370b360a7f332 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TBUCKET(P1D[DATE_PERIOD],@timestamp{f(DateEsField)}#0) AS tbucket(1 day)#1],[SUM(TODOUBLE(does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, tbucket(1 day){r}#1]] + \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#5, event_duration{f}#6, message{f}#7, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/query.esql new file mode 100644 index 0000000000000..8ee634876a9b7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data +| STATS s = SUM(does_not_exist::DOUBLE), c = COUNT(*) BY tbucket(1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..a606b9204678f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TBUCKET(P1D[DATE_PERIOD],@timestamp{f(DateEsField)}#0) AS tbucket(1 day)#1],[SUM(TODOUBLE(does_not_exist{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, tbucket(1 day){r}#1]] + \_Eval[[null[NULL] AS does_not_exist#2]] + \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#5, event_duration{f}#6, message{f}#7] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..cbf52dd9c02eb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketAggregateUnmapped/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data +| STATS s = SUM(does_not_exist::DOUBLE), c = COUNT(*) BY tbucket(1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..50bd7d1993840 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TBUCKET(PT1H[TIME_DURATION],@timestamp{f(DateEsField)}#0) AS tbucket(1 hour)#1, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#3, tbucket(1 hour){r}#1, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2]] + \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/query.esql new file mode 100644 index 0000000000000..33c3866fe3563 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM sample_data +| STATS c = COUNT(*) BY tbucket(1 hour), does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..fa9425fdce85b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Aggregate[[TBUCKET(PT1H[TIME_DURATION],@timestamp{f(DateEsField)}#0) AS tbucket(1 hour)#1, does_not_exist{r}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#3, tbucket(1 hour){r}#1, does_not_exist{r}#2]] + \_Eval[[null[NULL] AS does_not_exist#2]] + \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..0ddc50c5758d4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketGroupByUnmapped/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM sample_data +| STATS c = COUNT(*) BY tbucket(1 hour), does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..71e224132f7cd --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000000[INTEGER],false,false] +\_TimeSeriesAggregate[[_timeseries{f(EsField)}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f(DateEsField)}#1) AS tbucket(1 hour)#2],[VALUES(FIRSTOVERTIME(TODOUBLE(does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#3),true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f(DateEsField)}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS f#4, tbucket(1 hour){r}#2],null,@timestamp{f(DateEsField)}#1] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#5, cluster{f}#6, event{f}#7, event_city{f}#8, event_city_boundary{f}#9, event_location{f}#10, event_log{f}#11, event_shape{f}#12, events_received{f}#13, network.bytes_in{f}#14, network.cost{f}#15, network.eth0.currently_connected_clients{f}#16, network.eth0.firmware_version{f}#17, network.eth0.last_up{f}#18, network.eth0.rx{f}#19, network.eth0.tx{f}#20, network.eth0.up{f}#21, network.total_bytes_in{f}#22, network.total_bytes_out{f}#23, network.total_cost{f}#24, pod{f}#25, region{f}#26, _timeseries{f}#0, does_not_exist{f}#3] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/query.esql new file mode 100644 index 0000000000000..8cddd18499f03 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; TS k8s +| STATS f = FIRST_OVER_TIME(does_not_exist::DOUBLE) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..98c91207aa550 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000000[INTEGER],false,false] +\_TimeSeriesAggregate[[_timeseries{f(EsField)}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f(DateEsField)}#1) AS tbucket(1 hour)#2],[VALUES(FIRSTOVERTIME(TODOUBLE(does_not_exist{r}#3),true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f(DateEsField)}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS f#4, tbucket(1 hour){r}#2],null,@timestamp{f(DateEsField)}#1] + \_Eval[[null[NULL] AS does_not_exist#3]] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#5, cluster{f}#6, event{f}#7, event_city{f}#8, event_city_boundary{f}#9, event_location{f}#10, event_log{f}#11, event_shape{f}#12, events_received{f}#13, network.bytes_in{f}#14, network.cost{f}#15, network.eth0.currently_connected_clients{f}#16, network.eth0.firmware_version{f}#17, network.eth0.last_up{f}#18, network.eth0.rx{f}#19, network.eth0.tx{f}#20, network.eth0.up{f}#21, network.total_bytes_in{f}#22, network.total_bytes_out{f}#23, network.total_cost{f}#24, pod{f}#25, region{f}#26, _timeseries{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..830583a7048ff --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesFirstOverTimeUnmapped/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; TS k8s +| STATS f = FIRST_OVER_TIME(does_not_exist::DOUBLE) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..359c8bd55b39d --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000000[INTEGER],false,false] +\_TimeSeriesAggregate[[_timeseries{f(EsField)}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f(DateEsField)}#1) AS tbucket(1 hour)#2],[VALUES(RATE(does_not_exist{r}#3,true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f(DateEsField)}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS r#4, tbucket(1 hour){r}#2],null,@timestamp{f(DateEsField)}#1] + \_Eval[[null[NULL] AS does_not_exist#3]] + \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#5, cluster{f}#6, event{f}#7, event_city{f}#8, event_city_boundary{f}#9, event_location{f}#10, event_log{f}#11, event_shape{f}#12, events_received{f}#13, network.bytes_in{f}#14, network.cost{f}#15, network.eth0.currently_connected_clients{f}#16, network.eth0.firmware_version{f}#17, network.eth0.last_up{f}#18, network.eth0.rx{f}#19, network.eth0.tx{f}#20, network.eth0.up{f}#21, network.total_bytes_in{f}#22, network.total_bytes_out{f}#23, network.total_cost{f}#24, pod{f}#25, region{f}#26, _timeseries{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..f398daec38c45 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateUnmapped/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; TS k8s +| STATS r = RATE(does_not_exist) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/load/analysis.expected new file mode 100644 index 0000000000000..d413739fd03bc --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist{f}#0) > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/load/query.esql new file mode 100644 index 0000000000000..e713ad65f4f21 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| WHERE does_not_exist::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/analysis.expected new file mode 100644 index 0000000000000..d56f0e5969628 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist{r}#0) > 0[INTEGER]] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/query.esql new file mode 100644 index 0000000000000..3d9a2e14cc93c --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhere/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| WHERE does_not_exist::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/load/analysis.expected new file mode 100644 index 0000000000000..8d9fcfe30c2c2 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist1{f}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER] AND TOLONG(does_not_exist2{f}#2) < 100[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#1, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist1{f}#0, does_not_exist2{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/load/query.esql new file mode 100644 index 0000000000000..ca0a222d0d3c8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| WHERE does_not_exist1::LONG > 0 OR emp_no > 0 AND does_not_exist2::LONG < 100 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/analysis.expected new file mode 100644 index 0000000000000..6364f29c1da43 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist1{r}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER] AND TOLONG(does_not_exist2{r}#2) < 100[INTEGER]] + \_Eval[[null[NULL] AS does_not_exist1#0, null[NULL] AS does_not_exist2#2]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#1, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/query.esql new file mode 100644 index 0000000000000..6da7b544c73b8 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereComplex/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| WHERE does_not_exist1::LONG > 0 OR emp_no > 0 AND does_not_exist2::LONG < 100 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/load/analysis.expected new file mode 100644 index 0000000000000..4e5bd4c4b8b68 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/load/analysis.expected @@ -0,0 +1,3 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist{f}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#1, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/load/query.esql new file mode 100644 index 0000000000000..733eddf433f08 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| WHERE does_not_exist::LONG > 0 OR emp_no > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/analysis.expected new file mode 100644 index 0000000000000..f6c3ff4db63bb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Filter[TOLONG(does_not_exist{r}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER]] + \_Eval[[null[NULL] AS does_not_exist#0]] + \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#1, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/query.esql new file mode 100644 index 0000000000000..6a4dcd6d7226f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testWhereOr/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| WHERE does_not_exist::LONG > 0 OR emp_no > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/load/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/load/local_physical_optimization.expected index 2f56604505197..70b03417ea7e9 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/load/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/load/local_physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[message{f}#0, does_not_exist{f}#1]] +ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[message{f}#0, does_not_exist{f}#1],false] - \_ProjectExec[[message{f}#0, does_not_exist{f}#1]] + \_ExchangeExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1],false] + \_ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1]] \_FieldExtractExec[message{f}#0]<[],[]> \_LimitExec[1000[INTEGER],70] \_FilterExec[TOSTRING(does_not_exist{f}#1) == foo[KEYWORD]] diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected index 8f0caf6cc39a3..2edac90a57768 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected @@ -1 +1 @@ -LocalSourceExec[[message{f}#0, does_not_exist{r}#1],EMPTY] \ No newline at end of file +LocalSourceExec[[message{f(KeywordEsField)}#0, does_not_exist{r}#1],EMPTY] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/load/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/load/local_physical_optimization.expected index b3ff975b660ee..4ca521e2b086a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/load/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/load/local_physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[message{f}#0, does_not_exist{f}#1]] +ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[message{f}#0, does_not_exist{f}#1],false] - \_ProjectExec[[message{f}#0, does_not_exist{f}#1]] + \_ExchangeExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1],false] + \_ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1]] \_LimitExec[1000[INTEGER],120] \_FilterExec[message{f}#0 == Connection error?[KEYWORD] OR TOSTRING(does_not_exist{f}#1) == foo[KEYWORD]] \_FieldExtractExec[message{f}#0, does_not_exist{f}#1]<[],[]> diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected index e43a2df780fed..04bd52c16369c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterDisjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[message{f}#0, does_not_exist{r}#1]] +ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{r}#1]] \_EvalExec[[null[NULL] AS does_not_exist#1]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[message{f}#0],false] - \_ProjectExec[[message{f}#0]] + \_ExchangeExec[[message{f(KeywordEsField)}#0],false] + \_ProjectExec[[message{f(KeywordEsField)}#0]] \_FieldExtractExec[message{f}#0]<[],[]> \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#2], limit[1000], sort[] estimatedRowSize[54] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/local_physical_optimization.expected index 89814d11149b2..876bb13eb3c3f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/load/local_physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[message{f}#0, does_not_exist{f}#1]] +ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[message{f}#0, does_not_exist{f}#1],false] - \_ProjectExec[[message{f}#0, does_not_exist{f}#1]] + \_ExchangeExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1],false] + \_ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1]] \_FieldExtractExec[message{f}#0]<[],[]> \_LimitExec[1000[INTEGER],70] \_FilterExec[TOSTRING(does_not_exist{f}#1) == Connection error?[KEYWORD]] diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/nullify/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/nullify/local_physical_optimization.expected index 8f0caf6cc39a3..2edac90a57768 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/nullify/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterNoPushdownWithUnmapped/nullify/local_physical_optimization.expected @@ -1 +1 @@ -LocalSourceExec[[message{f}#0, does_not_exist{r}#1],EMPTY] \ No newline at end of file +LocalSourceExec[[message{f(KeywordEsField)}#0, does_not_exist{r}#1],EMPTY] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/local_physical_optimization.expected index aa4715e3b0414..881a2b8fbd51a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmapped/local_physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[message{f}#0]] +ProjectExec[[message{f(KeywordEsField)}#0]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[message{f}#0],false] - \_ProjectExec[[message{f}#0]] + \_ExchangeExec[[message{f(KeywordEsField)}#0],false] + \_ProjectExec[[message{f(KeywordEsField)}#0]] \_FieldExtractExec[message{f}#0]<[],[]> \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#1], limit[1000], sort[] estimatedRowSize[54] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmappedFilterOnly/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmappedFilterOnly/local_physical_optimization.expected index aa4715e3b0414..881a2b8fbd51a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmappedFilterOnly/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testFilterPushdownNoUnmappedFilterOnly/local_physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[message{f}#0]] +ProjectExec[[message{f(KeywordEsField)}#0]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[message{f}#0],false] - \_ProjectExec[[message{f}#0]] + \_ExchangeExec[[message{f(KeywordEsField)}#0],false] + \_ProjectExec[[message{f(KeywordEsField)}#0]] \_FieldExtractExec[message{f}#0]<[],[]> \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#1], limit[1000], sort[] estimatedRowSize[54] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/load/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/load/local_physical_optimization.expected index d7739a31c30d2..07008060b334a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/load/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/load/local_physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[message{f}#0, does_not_exist{f}#1]] -\_TopNExec[[Order[message{f}#0,ASC,LAST], Order[does_not_exist{f}#1,ASC,LAST]],5[INTEGER],null] - \_ExchangeExec[[message{f}#0, does_not_exist{f}#1],false] - \_ProjectExec[[message{f}#0, does_not_exist{f}#1]] - \_TopNExec[[Order[message{f}#0,ASC,LAST], Order[does_not_exist{f}#1,ASC,LAST]],5[INTEGER],120] +ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1]] +\_TopNExec[[Order[message{f(KeywordEsField)}#0,ASC,LAST], Order[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1],false] + \_ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1]] + \_TopNExec[[Order[message{f(KeywordEsField)}#0,ASC,LAST], Order[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1,ASC,LAST]],5[INTEGER],120] \_FieldExtractExec[message{f}#0, does_not_exist{f}#1]<[],[]> \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#2], limit[], sort[] estimatedRowSize[104] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected index 3dac4b94f8e4b..f2115b4a75bc6 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortConjunctionPushableAndNonPushable/nullify/local_physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[message{f}#0, does_not_exist{r}#1]] -\_TopNExec[[Order[message{f}#0,ASC,LAST], Order[does_not_exist{r}#1,ASC,LAST]],5[INTEGER],null] - \_ExchangeExec[[message{f}#0, does_not_exist{r}#1],false] - \_ProjectExec[[message{f}#0, does_not_exist{r}#1]] +ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{r}#1]] +\_TopNExec[[Order[message{f(KeywordEsField)}#0,ASC,LAST], Order[does_not_exist{r}#1,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[message{f(KeywordEsField)}#0, does_not_exist{r}#1],false] + \_ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{r}#1]] \_FieldExtractExec[message{f}#0]<[],[]> \_EvalExec[[null[NULL] AS does_not_exist#1]] \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#2], limit[5], sort[[FieldSort[field=message{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/load/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/load/local_physical_optimization.expected index ac325cce5294d..40ae63b04242d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/load/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/load/local_physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[message{f}#0, does_not_exist{f}#1]] -\_TopNExec[[Order[does_not_exist{f}#1,ASC,LAST]],5[INTEGER],null] - \_ExchangeExec[[message{f}#0, does_not_exist{f}#1],false] - \_ProjectExec[[message{f}#0, does_not_exist{f}#1]] +ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1]] +\_TopNExec[[Order[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1],false] + \_ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1]] \_FieldExtractExec[message{f}#0]<[],[]> - \_TopNExec[[Order[does_not_exist{f}#1,ASC,LAST]],5[INTEGER],120] + \_TopNExec[[Order[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1,ASC,LAST]],5[INTEGER],120] \_FieldExtractExec[does_not_exist{f}#1]<[],[]> \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#2], limit[], sort[] estimatedRowSize[54] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/nullify/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/nullify/local_physical_optimization.expected index ea4e1b4e5134b..d906991993cb5 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/nullify/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortNoPushdownWithUnmapped/nullify/local_physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[message{f}#0, does_not_exist{r}#1]] +ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{r}#1]] \_TopNExec[[Order[does_not_exist{r}#1,ASC,LAST]],5[INTEGER],null] - \_ExchangeExec[[message{f}#0, does_not_exist{r}#1],false] - \_ProjectExec[[message{f}#0, does_not_exist{r}#1]] + \_ExchangeExec[[message{f(KeywordEsField)}#0, does_not_exist{r}#1],false] + \_ProjectExec[[message{f(KeywordEsField)}#0, does_not_exist{r}#1]] \_FieldExtractExec[message{f}#0]<[],[]> \_TopNExec[[Order[does_not_exist{r}#1,ASC,LAST]],5[INTEGER],70] \_EvalExec[[null[NULL] AS does_not_exist#1]] diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortPushdownNoUnmapped/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortPushdownNoUnmapped/local_physical_optimization.expected index f758f6bba7277..664ba1dcc7be6 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortPushdownNoUnmapped/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/golden_tests/PushdownGoldenTests/testSortPushdownNoUnmapped/local_physical_optimization.expected @@ -1,6 +1,6 @@ -ProjectExec[[message{f}#0]] -\_TopNExec[[Order[message{f}#0,ASC,LAST]],5[INTEGER],null] - \_ExchangeExec[[message{f}#0],false] - \_ProjectExec[[message{f}#0]] +ProjectExec[[message{f(KeywordEsField)}#0]] +\_TopNExec[[Order[message{f(KeywordEsField)}#0,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[message{f(KeywordEsField)}#0],false] + \_ProjectExec[[message{f(KeywordEsField)}#0]] \_FieldExtractExec[message{f}#0]<[],[]> \_EsQueryExec[sample_data], indexMode[standard], [_doc{f}#1], limit[5], sort[[FieldSort[field=message{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected index 504e54c3064ee..e8673db3d1c8d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/bucket/local_physical_optimization.expected @@ -2,10 +2,10 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],SINGLE,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_EvalExec[[BUCKET(date{r}#4,P1D[DATE_PERIOD]) AS x#0]] \_MergeExec[[date{r}#4]] - |_ProjectExec[[date{f}#5]] + |_ProjectExec[[date{f(DateEsField)}#5]] | \_LimitExec[1000[INTEGER],null] - | \_ExchangeExec[[date{f}#5],false] - | \_ProjectExec[[date{f}#5]] + | \_ExchangeExec[[date{f(DateEsField)}#5],false] + | \_ProjectExec[[date{f(DateEsField)}#5]] | \_FieldExtractExec[date{f}#5]<[],[]> | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#6], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { @@ -21,10 +21,10 @@ LimitExec[1000[INTEGER],null] "source" : "integer > 100@2:15" } }, tags=[]]]] - \_ProjectExec[[date{f}#7]] + \_ProjectExec[[date{f(DateEsField)}#7]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[date{f}#7],false] - \_ProjectExec[[date{f}#7]] + \_ExchangeExec[[date{f(DateEsField)}#7],false] + \_ProjectExec[[date{f(DateEsField)}#7]] \_FieldExtractExec[date{f}#7]<[],[]> \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "match" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected index 72dbdcc974f68..5375b59ec8cef 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/date_trunc/local_physical_optimization.expected @@ -2,10 +2,10 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],SINGLE,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_EvalExec[[DATETRUNC(P1D[DATE_PERIOD],date{r}#4) AS x#0]] \_MergeExec[[date{r}#4]] - |_ProjectExec[[date{f}#5]] + |_ProjectExec[[date{f(DateEsField)}#5]] | \_LimitExec[1000[INTEGER],null] - | \_ExchangeExec[[date{f}#5],false] - | \_ProjectExec[[date{f}#5]] + | \_ExchangeExec[[date{f(DateEsField)}#5],false] + | \_ProjectExec[[date{f(DateEsField)}#5]] | \_FieldExtractExec[date{f}#5]<[],[]> | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#6], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { @@ -21,10 +21,10 @@ LimitExec[1000[INTEGER],null] "source" : "integer > 100@2:15" } }, tags=[]]]] - \_ProjectExec[[date{f}#7]] + \_ProjectExec[[date{f(DateEsField)}#7]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[date{f}#7],false] - \_ProjectExec[[date{f}#7]] + \_ExchangeExec[[date{f(DateEsField)}#7],false] + \_ProjectExec[[date{f(DateEsField)}#7]] \_FieldExtractExec[date{f}#7]<[],[]> \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "match" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected index 5c5cb8da952c2..0ba82653fa90c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithFork/round_to/local_physical_optimization.expected @@ -2,10 +2,10 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],SINGLE,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_EvalExec[[ROUNDTO(date{r}#4,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] \_MergeExec[[date{r}#4]] - |_ProjectExec[[date{f}#5]] + |_ProjectExec[[date{f(DateEsField)}#5]] | \_LimitExec[1000[INTEGER],null] - | \_ExchangeExec[[date{f}#5],false] - | \_ProjectExec[[date{f}#5]] + | \_ExchangeExec[[date{f(DateEsField)}#5],false] + | \_ProjectExec[[date{f(DateEsField)}#5]] | \_FieldExtractExec[date{f}#5]<[],[]> | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#6], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { @@ -21,10 +21,10 @@ LimitExec[1000[INTEGER],null] "source" : "integer > 100@2:15" } }, tags=[]]]] - \_ProjectExec[[date{f}#7]] + \_ProjectExec[[date{f(DateEsField)}#7]] \_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[date{f}#7],false] - \_ProjectExec[[date{f}#7]] + \_ExchangeExec[[date{f(DateEsField)}#7],false] + \_ProjectExec[[date{f(DateEsField)}#7]] \_FieldExtractExec[date{f}#7]<[],[]> \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "match" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected index 37d5c04ccc89b..48ca6656e3cd0 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/bucket/local_physical_optimization.expected @@ -2,9 +2,9 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[ROUNDTO(date{f}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] + \_EvalExec[[ROUNDTO(date{f(DateEsField)}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] \_FieldExtractExec[date{f}#6]<[],[]> - \_LookupJoinExec[[integer{f}#7],[language_code{f}#8],[],null] + \_LookupJoinExec[[integer{f(EsField)}#7],[language_code{f(EsField)}#8],[],null] |_FieldExtractExec[integer{f}#7]<[],[]> | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#9], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected index 37d5c04ccc89b..48ca6656e3cd0 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/date_trunc/local_physical_optimization.expected @@ -2,9 +2,9 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[ROUNDTO(date{f}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] + \_EvalExec[[ROUNDTO(date{f(DateEsField)}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] \_FieldExtractExec[date{f}#6]<[],[]> - \_LookupJoinExec[[integer{f}#7],[language_code{f}#8],[],null] + \_LookupJoinExec[[integer{f(EsField)}#7],[language_code{f(EsField)}#8],[],null] |_FieldExtractExec[integer{f}#7]<[],[]> | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#9], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected index 37d5c04ccc89b..48ca6656e3cd0 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketNotTransformToQueryAndTagsWithLookupJoin/round_to/local_physical_optimization.expected @@ -2,9 +2,9 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[ROUNDTO(date{f}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] + \_EvalExec[[ROUNDTO(date{f(DateEsField)}#6,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#0]] \_FieldExtractExec[date{f}#6]<[],[]> - \_LookupJoinExec[[integer{f}#7],[language_code{f}#8],[],null] + \_LookupJoinExec[[integer{f(EsField)}#7],[language_code{f(EsField)}#8],[],null] |_FieldExtractExec[integer{f}#7]<[],[]> | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#9], limit[], sort[] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected index 9bed443f7dbca..4b49127073688 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/bucket/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] +\_AggregateExec[[x{r}#0],[SUM(long{f(EsField)}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] \_ExchangeExec[[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],true] - \_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] + \_AggregateExec[[x{r}#0],[SUM(long{f(EsField)}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] \_FieldExtractExec[long{f}#1]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f}#12 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#12 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#13, $$date$round_to$datetime{f}#12], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected index 8a37befcc7c7e..bc224463f20da 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/date_trunc/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] +\_AggregateExec[[x{r}#0],[SUM(long{f(EsField)}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] \_ExchangeExec[[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],true] - \_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] + \_AggregateExec[[x{r}#0],[SUM(long{f(EsField)}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] \_FieldExtractExec[long{f}#1]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f}#12 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#12 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#13, $$date$round_to$datetime{f}#12], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected index dd6350bd70a36..45bd1357a9060 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithMultipleAggregates/round_to/local_physical_optimization.expected @@ -1,9 +1,9 @@ LimitExec[1000[INTEGER],null] -\_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] +\_AggregateExec[[x{r}#0],[SUM(long{f(EsField)}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],FINAL,[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],null] \_ExchangeExec[[x{r}#0, $$sum(long)$sum{r}#4, $$sum(long)$seen{r}#5, $$count(*)$count{r}#6, $$count(*)$seen{r}#7],true] - \_AggregateExec[[x{r}#0],[SUM(long{f}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] + \_AggregateExec[[x{r}#0],[SUM(long{f(EsField)}#1,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS sum(long)#2, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#3, x{r}#0],INITIAL,[x{r}#0, $$sum(long)$sum{r}#8, $$sum(long)$seen{r}#9, $$count(*)$count{r}#10, $$count(*)$seen{r}#11],24] \_FieldExtractExec[long{f}#1]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f}#12 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#12 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#13, $$date$round_to$datetime{f}#12], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected index 8b039c4db5c27..9e5e8117ad64c 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_equality/local_physical_optimization.expected @@ -2,7 +2,7 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#6 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected index 1783e8bca9fb9..1844a19d493e8 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/bucket/keyword_match/local_physical_optimization.expected @@ -2,7 +2,7 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#6 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected index 741c5cc853d00..e4c62c4a8e048 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_equality/local_physical_optimization.expected @@ -2,7 +2,7 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#6 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected index ba745f8603cf2..06e902b264e67 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/date_trunc/keyword_match/local_physical_optimization.expected @@ -2,7 +2,7 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#6 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected index 3bb91af178169..7ee987d4dd704 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_equality/local_physical_optimization.expected @@ -2,7 +2,7 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#6 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected index 0adf9b4716949..717191ed291d6 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithOtherPushdownFunctions/round_to/keyword_match/local_physical_optimization.expected @@ -2,7 +2,7 @@ LimitExec[1000[INTEGER],null] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],FINAL,[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],null] \_ExchangeExec[[x{r}#0, $$count(*)$count{r}#2, $$count(*)$seen{r}#3],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#1, x{r}#0],INITIAL,[x{r}#0, $$count(*)$count{r}#4, $$count(*)$seen{r}#5],16] - \_EvalExec[[$$date$round_to$datetime{f}#6 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#6 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#7, $$date$round_to$datetime{f}#6], limit[], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query={ "bool" : { "filter" : [ diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected index 54ec4005471fb..4b9a4f78f2b83 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/bucket/local_physical_optimization.expected @@ -3,7 +3,7 @@ LimitExec[1000[INTEGER],null] \_ExchangeExec[[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],INITIAL,[x{r}#0, $$count(*) where long > 10$count{r}#5, $$count(*) where long > 10$seen{r}#6],16] \_FieldExtractExec[long{f}#1]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f}#7 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#7 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8, $$date$round_to$datetime{f}#7], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected index 8665d69bc4af1..fad943e8cfcc5 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/date_trunc/local_physical_optimization.expected @@ -3,7 +3,7 @@ LimitExec[1000[INTEGER],null] \_ExchangeExec[[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],INITIAL,[x{r}#0, $$count(*) where long > 10$count{r}#5, $$count(*) where long > 10$seen{r}#6],16] \_FieldExtractExec[long{f}#1]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f}#7 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#7 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8, $$date$round_to$datetime{f}#7], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected index d59fd1a30f5dc..266ce4e2b05d7 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncBucketTransformToQueryAndTagsWithWhereInsideAggregation/round_to/local_physical_optimization.expected @@ -3,7 +3,7 @@ LimitExec[1000[INTEGER],null] \_ExchangeExec[[x{r}#0, $$count(*) where long > 10$count{r}#3, $$count(*) where long > 10$seen{r}#4],true] \_AggregateExec[[x{r}#0],[COUNT(*[KEYWORD],long{f}#1 > 10[INTEGER],PT0S[TIME_DURATION]) AS count(*) where long > 10#2, x{r}#0],INITIAL,[x{r}#0, $$count(*) where long > 10$count{r}#5, $$count(*) where long > 10$seen{r}#6],16] \_FieldExtractExec[long{f}#1]<[],[]> - \_EvalExec[[$$date$round_to$datetime{f}#7 AS x#0]] + \_EvalExec[[$$date$round_to$datetime{f(EsField)}#7 AS x#0]] \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#8, $$date$round_to$datetime{f}#7], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected index f4aec5a235e42..930a27274aec3 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/date_trunc/local_physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] -\_TopNExec[[Order[date{f}#0,ASC,LAST]],5[INTEGER],null] - \_ExchangeExec[[!alias_integer, date{f}#0, x{r}#1],false] - \_ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] +ProjectExec[[!alias_integer, date{f(DateEsField)}#0, x{r}#1]] +\_TopNExec[[Order[date{f(DateEsField)}#0,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[!alias_integer, date{f(DateEsField)}#0, x{r}#1],false] + \_ProjectExec[[!alias_integer, date{f(DateEsField)}#0, x{r}#1]] \_FieldExtractExec[!alias_integer]<[],[]> - \_EvalExec[[ROUNDTO(date{f}#0,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#1]] + \_EvalExec[[ROUNDTO(date{f(DateEsField)}#0,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#1]] \_FieldExtractExec[date{f}#0]<[],[]> \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#2], limit[5], sort[[FieldSort[field=date{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[1056] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected index f4aec5a235e42..930a27274aec3 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testDateTruncNotTransformToQueryAndTags/round_to/local_physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] -\_TopNExec[[Order[date{f}#0,ASC,LAST]],5[INTEGER],null] - \_ExchangeExec[[!alias_integer, date{f}#0, x{r}#1],false] - \_ProjectExec[[!alias_integer, date{f}#0, x{r}#1]] +ProjectExec[[!alias_integer, date{f(DateEsField)}#0, x{r}#1]] +\_TopNExec[[Order[date{f(DateEsField)}#0,ASC,LAST]],5[INTEGER],null] + \_ExchangeExec[[!alias_integer, date{f(DateEsField)}#0, x{r}#1],false] + \_ProjectExec[[!alias_integer, date{f(DateEsField)}#0, x{r}#1]] \_FieldExtractExec[!alias_integer]<[],[]> - \_EvalExec[[ROUNDTO(date{f}#0,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#1]] + \_EvalExec[[ROUNDTO(date{f(DateEsField)}#0,1697760000000[DATETIME],1697846400000[DATETIME],1697932800000[DATETIME],1698019200000[DATETIME]) AS x#1]] \_FieldExtractExec[date{f}#0]<[],[]> \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#2], limit[5], sort[[FieldSort[field=date{f}#0, direction=ASC, nulls=LAST]]] estimatedRowSize[1056] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected index d6af15a5d5b6f..ef73b853c3e12 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testForkWithStatsCountStarDateTrunc/local_physical_optimization.expected @@ -3,11 +3,11 @@ LimitExec[1000[INTEGER],null] |_ProjectExec[[x{r}#4, y{r}#5, hd{r}#6, _fork{r}#7]] | \_EvalExec[[fork1[KEYWORD] AS _fork#7]] | \_LimitExec[1000[INTEGER],null] - | \_AggregateExec[[hd{r}#6],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#4, MAX(long{f}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#5, hd{r}#6],FINAL,[hd{r}#6, $$x$count{r}#9, $$x$seen{r}#10, $$y$max{r}#11, $$y$seen{r}#12],null] + | \_AggregateExec[[hd{r}#6],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#4, MAX(long{f(EsField)}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#5, hd{r}#6],FINAL,[hd{r}#6, $$x$count{r}#9, $$x$seen{r}#10, $$y$max{r}#11, $$y$seen{r}#12],null] | \_ExchangeExec[[hd{r}#6, $$x$count{r}#9, $$x$seen{r}#10, $$y$max{r}#11, $$y$seen{r}#12],true] - | \_AggregateExec[[hd{r}#6],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#4, MAX(long{f}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#5, hd{r}#6],INITIAL,[hd{r}#6, $$x$count{r}#13, $$x$seen{r}#14, $$y$max{r}#15, $$y$seen{r}#16],24] + | \_AggregateExec[[hd{r}#6],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#4, MAX(long{f(EsField)}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#5, hd{r}#6],INITIAL,[hd{r}#6, $$x$count{r}#13, $$x$seen{r}#14, $$y$max{r}#15, $$y$seen{r}#16],24] | \_FieldExtractExec[long{f}#8]<[],[]> - | \_EvalExec[[$$date$round_to$datetime{f}#17 AS hd#6]] + | \_EvalExec[[$$date$round_to$datetime{f(EsField)}#17 AS hd#6]] | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#18, $$date$round_to$datetime{f}#17], limit[], sort[] estimatedRowSize[20] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { "field" : "date", @@ -86,10 +86,10 @@ LimitExec[1000[INTEGER],null] \_ProjectExec[[x{r}#19, y{r}#20, hd{r}#21, _fork{r}#7]] \_EvalExec[[fork2[KEYWORD] AS _fork#7]] \_LimitExec[1000[INTEGER],null] - \_AggregateExec[[hd{r}#21],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#19, MIN(long{f}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#20, hd{r}#21],FINAL,[hd{r}#21, $$x$count{r}#23, $$x$seen{r}#24, $$y$min{r}#25, $$y$seen{r}#26],null] + \_AggregateExec[[hd{r}#21],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#19, MIN(long{f(EsField)}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#20, hd{r}#21],FINAL,[hd{r}#21, $$x$count{r}#23, $$x$seen{r}#24, $$y$min{r}#25, $$y$seen{r}#26],null] \_ExchangeExec[[hd{r}#21, $$x$count{r}#23, $$x$seen{r}#24, $$y$min{r}#25, $$y$seen{r}#26],true] - \_AggregateExec[[hd{r}#21],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#19, MIN(long{f}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#20, hd{r}#21],INITIAL,[hd{r}#21, $$x$count{r}#27, $$x$seen{r}#28, $$y$min{r}#29, $$y$seen{r}#30],24] + \_AggregateExec[[hd{r}#21],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS x#19, MIN(long{f(EsField)}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#20, hd{r}#21],INITIAL,[hd{r}#21, $$x$count{r}#27, $$x$seen{r}#28, $$y$min{r}#29, $$y$seen{r}#30],24] \_FieldExtractExec[long{f}#22]<[],[]> - \_EvalExec[[DATETRUNC(P2D[DATE_PERIOD],date{f}#31) AS hd#21]] + \_EvalExec[[DATETRUNC(P2D[DATE_PERIOD],date{f(DateEsField)}#31) AS hd#21]] \_FieldExtractExec[date{f}#31]<[],[]> \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#32], limit[], sort[] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected index 9f3fe63e4a21f..97b2db7cb91bf 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/golden_tests/SubstituteRoundToGoldenTests/testSubqueryWithCountStarAndDateTrunc/local_physical_optimization.expected @@ -1,8 +1,8 @@ ProjectExec[[x{r}#0, cnt{r}#1, date{r}#2]] \_LimitExec[1000[INTEGER],null] \_MergeExec[[alias_integer{r}#3, boolean{r}#4, byte{r}#5, constant_keyword-foo{r}#6, date{r}#2, date_nanos{r}#7, dense_vector{r}#8, double{r}#9, float{r}#10, half_float{r}#11, integer{r}#12, ip{r}#13, keyword{r}#14, long{r}#15, scaled_float{r}#16, semantic_text{r}#17, short{r}#18, text{r}#19, unsigned_long{r}#20, version{r}#21, wildcard{r}#22, cnt{r}#1, x{r}#0]] - |_ExchangeExec[[alias_integer{r}#23, boolean{f}#24, byte{f}#25, constant_keyword-foo{f}#26, date{f}#27, date_nanos{f}#28, dense_vector{f}#29, double{f}#30, float{f}#31, half_float{f}#32, integer{f}#33, ip{f}#34, keyword{f}#35, long{f}#36, scaled_float{f}#37, semantic_text{f}#38, short{f}#39, text{f}#40, unsigned_long{f}#41, version{f}#42, wildcard{f}#43, cnt{r}#44, x{r}#45],false] - | \_ProjectExec[[alias_integer{r}#23, boolean{f}#24, byte{f}#25, constant_keyword-foo{f}#26, date{f}#27, date_nanos{f}#28, dense_vector{f}#29, double{f}#30, float{f}#31, half_float{f}#32, integer{f}#33, ip{f}#34, keyword{f}#35, long{f}#36, scaled_float{f}#37, semantic_text{f}#38, short{f}#39, text{f}#40, unsigned_long{f}#41, version{f}#42, wildcard{f}#43, cnt{r}#44, x{r}#45]] + |_ExchangeExec[[alias_integer{r}#23, boolean{f(EsField)}#24, byte{f(EsField)}#25, constant_keyword-foo{f(KeywordEsField)}#26, date{f(DateEsField)}#27, date_nanos{f(EsField)}#28, dense_vector{f(EsField)}#29, double{f(EsField)}#30, float{f(EsField)}#31, half_float{f(EsField)}#32, integer{f(EsField)}#33, ip{f(EsField)}#34, keyword{f(KeywordEsField)}#35, long{f(EsField)}#36, scaled_float{f(EsField)}#37, semantic_text{f(TextEsField)}#38, short{f(EsField)}#39, text{f(TextEsField)}#40, unsigned_long{f(EsField)}#41, version{f(EsField)}#42, wildcard{f(KeywordEsField)}#43, cnt{r}#44, x{r}#45],false] + | \_ProjectExec[[alias_integer{r}#23, boolean{f(EsField)}#24, byte{f(EsField)}#25, constant_keyword-foo{f(KeywordEsField)}#26, date{f(DateEsField)}#27, date_nanos{f(EsField)}#28, dense_vector{f(EsField)}#29, double{f(EsField)}#30, float{f(EsField)}#31, half_float{f(EsField)}#32, integer{f(EsField)}#33, ip{f(EsField)}#34, keyword{f(KeywordEsField)}#35, long{f(EsField)}#36, scaled_float{f(EsField)}#37, semantic_text{f(TextEsField)}#38, short{f(EsField)}#39, text{f(TextEsField)}#40, unsigned_long{f(EsField)}#41, version{f(EsField)}#42, wildcard{f(KeywordEsField)}#43, cnt{r}#44, x{r}#45]] | \_FieldExtractExec[boolean{f}#24, byte{f}#25, constant_keyword-foo{f}#26, date{f}#27, date_nanos{f}#28, dense_vector{f}#29, double{f}#30, float{f}#31, half_float{f}#32, integer{f}#33, ip{f}#34, keyword{f}#35, long{f}#36, scaled_float{f}#37, semantic_text{f}#38, short{f}#39, text{f}#40, unsigned_long{f}#41, version{f}#42, wildcard{f}#43]<[],[]> | \_EvalExec[[null[LONG] AS cnt#44, null[DATETIME] AS x#45, null[KEYWORD] AS alias_integer#23]] | \_EsQueryExec[all_types], indexMode[standard], [_doc{f}#46], limit[], sort[] estimatedRowSize[6472] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected index fb387032f3d2a..7670a902dd6e9 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] -\_ProjectExec[[_doc{f}#0, hire_date{f}#1]] +ExchangeSinkExec[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1],false] +\_ProjectExec[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1]] \_FieldExtractExec[hire_date{f}#1]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected index 9db0da8910f5b..cfbde5a0c88b3 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] +ExchangeSinkExec[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#0, hire_date{f}#1]] -\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] +Project[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#1, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected index 4b4fc0c891ac1..b4351eb176c15 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] +\_ProjectExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2]] \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> - \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file + \_TopNExec[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected index 84b502cae4e25..fac7b0beb280e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testBasicTopNLateMaterialization/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] -\_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] +ProjectExec[[hire_date{f(DateEsField)}#0, salary{f(EsField)}#1, emp_no{f(EsField)}#2]] +\_TopNExec[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] -\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] +Project[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected index 0315e1603645a..dd34dcd92d3a3 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_physical_optimization_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}#0, $$order_by$0{r}#1],false] -\_ProjectExec[[_doc{f}#0, $$order_by$0{r}#1]] +ExchangeSinkExec[[_doc{f(EsField)}#0, $$order_by$0{r}#1],false] +\_ProjectExec[[_doc{f(EsField)}#0, $$order_by$0{r}#1]] \_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],36] \_EvalExec[[SIN(height{f}#2) * 2[INTEGER] AS $$order_by$0#1]] \_FieldExtractExec[height{f}#2]<[],[]> diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected index 42e09257b6138..6078e7e0daa9e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[_doc{f}#0, $$order_by$0{r}#1],false] +ExchangeSinkExec[[_doc{f(EsField)}#0, $$order_by$0{r}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#0, $$order_by$0{r}#1]] +Project[[_doc{f(EsField)}#0, $$order_by$0{r}#1]] \_TopN[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],false] \_Eval[[SIN(height{f}#2) * 2[INTEGER] AS $$order_by$0#1]] \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#2, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected index d2459818c5588..8a01de5d8a548 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[hire_date{f}#0, $$order_by$0{r}#1],false] -\_ProjectExec[[hire_date{f}#0, $$order_by$0{r}#1]] +ExchangeSinkExec[[hire_date{f(DateEsField)}#0, $$order_by$0{r}#1],false] +\_ProjectExec[[hire_date{f(DateEsField)}#0, $$order_by$0{r}#1]] \_FieldExtractExec[hire_date{f}#0]<[],[]> \_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#2, $$order_by$0{r}#1],false] \ No newline at end of file + \_ExchangeSourceExec[[_doc{f(EsField)}#2, $$order_by$0{r}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected index 71abdab6b07fe..1d2b47bd3d1a2 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepAfterSort/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}#0]] +ProjectExec[[hire_date{f(DateEsField)}#0]] \_TopNExec[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[hire_date{f}#0, $$order_by$0{r}#1],false] + \_ExchangeExec[[hire_date{f(DateEsField)}#0, $$order_by$0{r}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[hire_date{f}#0, $$order_by$0{r}#1]] +Project[[hire_date{f(DateEsField)}#0, $$order_by$0{r}#1]] \_TopN[[Order[$$order_by$0{r}#1,ASC,LAST]],20[INTEGER],false] \_Eval[[SIN(height{f}#2) * 2[INTEGER] AS $$order_by$0#1]] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#2, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected index f1a5151c994d2..ffdc91536d7ad 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_physical_optimization_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}#0, height{f}#1, $$order_by$0{r}#2],false] -\_ProjectExec[[_doc{f}#0, height{f}#1, $$order_by$0{r}#2]] +ExchangeSinkExec[[_doc{f(EsField)}#0, height{f(EsField)}#1, $$order_by$0{r}#2],false] +\_ProjectExec[[_doc{f(EsField)}#0, height{f(EsField)}#1, $$order_by$0{r}#2]] \_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],36] \_EvalExec[[SIN(height{f}#1) * 2[INTEGER] AS $$order_by$0#2]] \_FieldExtractExec[height{f}#1]<[],[]> diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected index 202cc12a29fe2..23c36fb47dfe6 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[_doc{f}#0, height{f}#1, $$order_by$0{r}#2],false] +ExchangeSinkExec[[_doc{f(EsField)}#0, height{f(EsField)}#1, $$order_by$0{r}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#0, height{f}#1, $$order_by$0{r}#2]] +Project[[_doc{f(EsField)}#0, height{f(EsField)}#1, $$order_by$0{r}#2]] \_TopN[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],false] \_Eval[[SIN(height{f}#1) * 2[INTEGER] AS $$order_by$0#2]] \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#1, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected index 88c85960c5dd2..ecc7f70c306ad 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2],false] -\_ProjectExec[[height{f}#0, hire_date{f}#1, $$order_by$0{r}#2]] +ExchangeSinkExec[[height{f(EsField)}#0, hire_date{f(DateEsField)}#1, $$order_by$0{r}#2],false] +\_ProjectExec[[height{f(EsField)}#0, hire_date{f(DateEsField)}#1, $$order_by$0{r}#2]] \_FieldExtractExec[hire_date{f}#1]<[],[]> \_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],44] - \_ExchangeSourceExec[[_doc{f}#3, height{f}#0, $$order_by$0{r}#2],false] \ No newline at end of file + \_ExchangeSourceExec[[_doc{f(EsField)}#3, height{f(EsField)}#0, $$order_by$0{r}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected index b3fbad771e03e..56453d62cad8f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testExpressionSortTopNKeepBeforeSort/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}#0, height{f}#1]] +ProjectExec[[hire_date{f(DateEsField)}#0, height{f(EsField)}#1]] \_TopNExec[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[height{f}#1, hire_date{f}#0, $$order_by$0{r}#2],false] + \_ExchangeExec[[height{f(EsField)}#1, hire_date{f(DateEsField)}#0, $$order_by$0{r}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[height{f}#1, hire_date{f}#0, $$order_by$0{r}#2]] +Project[[height{f(EsField)}#1, hire_date{f(DateEsField)}#0, $$order_by$0{r}#2]] \_TopN[[Order[$$order_by$0{r}#2,ASC,LAST]],20[INTEGER],false] \_Eval[[SIN(height{f}#1) * 2[INTEGER] AS $$order_by$0#2]] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#1, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected index 0b739f1210f4d..038c996be7db5 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_physical_optimization_data_driver.expected @@ -1,9 +1,9 @@ -ExchangeSinkExec[[_doc{f}#0, emp_no{f}#1, languages{f}#2, language_code{r}#3, language_name{f}#4],false] -\_ProjectExec[[_doc{f}#0, emp_no{f}#1, languages{f}#2, language_code{r}#3, language_name{f}#4]] - \_TopNExec[[Order[emp_no{f}#1,ASC,LAST]],20[INTEGER],82] +ExchangeSinkExec[[_doc{f(EsField)}#0, emp_no{f(EsField)}#1, languages{f(EsField)}#2, language_code{r}#3, language_name{f(KeywordEsField)}#4],false] +\_ProjectExec[[_doc{f(EsField)}#0, emp_no{f(EsField)}#1, languages{f(EsField)}#2, language_code{r}#3, language_name{f(KeywordEsField)}#4]] + \_TopNExec[[Order[emp_no{f(EsField)}#1,ASC,LAST]],20[INTEGER],82] \_FieldExtractExec[emp_no{f}#1]<[],[]> - \_LookupJoinExec[[language_code{r}#3],[language_code{f}#5],[language_name{f}#4],null] - |_EvalExec[[languages{f}#2 AS language_code#3]] + \_LookupJoinExec[[language_code{r}#3],[language_code{f(EsField)}#5],[language_name{f(KeywordEsField)}#4],null] + |_EvalExec[[languages{f(EsField)}#2 AS language_code#3]] | \_FieldExtractExec[languages{f}#2]<[],[]> | \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[], sort[] estimatedRowSize[66] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected index 8f1164f38c747..5072ba8864888 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_data_driver.expected @@ -1,9 +1,9 @@ -ExchangeSinkExec[[_doc{f}#0, emp_no{f}#1, languages{f}#2, language_code{r}#3, language_name{f}#4],false] +ExchangeSinkExec[[_doc{f(EsField)}#0, emp_no{f(EsField)}#1, languages{f(EsField)}#2, language_code{r}#3, language_name{f(KeywordEsField)}#4],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#0, emp_no{f}#1, languages{f}#2, language_code{r}#3, language_name{f}#4]] -\_TopN[[Order[emp_no{f}#1,ASC,LAST]],20[INTEGER],false] - \_Join[LEFT,[language_code{r}#3],[language_code{f}#5],null] - |_Eval[[languages{f}#2 AS language_code#3]] +Project[[_doc{f(EsField)}#0, emp_no{f(EsField)}#1, languages{f(EsField)}#2, language_code{r}#3, language_name{f(KeywordEsField)}#4]] +\_TopN[[Order[emp_no{f(EsField)}#1,ASC,LAST]],20[INTEGER],false] + \_Join[LEFT,[language_code{r}#3],[language_code{f(EsField)}#5],null] + |_Eval[[languages{f(EsField)}#2 AS language_code#3]] | \_Filter[emp_no{f}#1 >= 10091[INTEGER] AND emp_no{f}#1 < 10094[INTEGER]] | \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#1, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#2, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26] \_EsRelation[languages_lookup][LOOKUP][language_code{f}#5, language_name{f}#4]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected index 19c98b1780f37..d6ecc720cbde4 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] -\_ProjectExec[[avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24]] +ExchangeSinkExec[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2, first_name{f(KeywordEsField)}#3, gender{f(KeywordEsField)}#4, height{f(EsField)}#5, height.float{f(EsField)}#6, height.half_float{f(EsField)}#7, height.scaled_float{f(EsField)}#8, hire_date{f(DateEsField)}#9, is_rehired{f(EsField)}#10, job_positions{f(KeywordEsField)}#11, languages{f(EsField)}#12, languages.byte{f(EsField)}#13, languages.long{f(EsField)}#14, languages.short{f(EsField)}#15, last_name{f(KeywordEsField)}#16, salary{f(EsField)}#17, salary_change{f(EsField)}#18, salary_change.int{f(EsField)}#19, salary_change.keyword{f(KeywordEsField)}#20, salary_change.long{f(EsField)}#21, still_hired{f(EsField)}#22, language_code{r}#23, language_name{f(KeywordEsField)}#24],false] +\_ProjectExec[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2, first_name{f(KeywordEsField)}#3, gender{f(KeywordEsField)}#4, height{f(EsField)}#5, height.float{f(EsField)}#6, height.half_float{f(EsField)}#7, height.scaled_float{f(EsField)}#8, hire_date{f(DateEsField)}#9, is_rehired{f(EsField)}#10, job_positions{f(KeywordEsField)}#11, languages{f(EsField)}#12, languages.byte{f(EsField)}#13, languages.long{f(EsField)}#14, languages.short{f(EsField)}#15, last_name{f(KeywordEsField)}#16, salary{f(EsField)}#17, salary_change{f(EsField)}#18, salary_change.int{f(EsField)}#19, salary_change.keyword{f(KeywordEsField)}#20, salary_change.long{f(EsField)}#21, still_hired{f(EsField)}#22, language_code{r}#23, language_name{f(KeywordEsField)}#24]] \_FieldExtractExec[avg_worked_seconds{f}#0, birth_date{f}#1, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<[],[]> - \_TopNExec[[Order[emp_no{f}#2,ASC,LAST]],20[INTEGER],430] - \_ExchangeSourceExec[[_doc{f}#25, emp_no{f}#2, languages{f}#12, language_code{r}#23, language_name{f}#24],false] \ No newline at end of file + \_TopNExec[[Order[emp_no{f(EsField)}#2,ASC,LAST]],20[INTEGER],430] + \_ExchangeSourceExec[[_doc{f(EsField)}#25, emp_no{f(EsField)}#2, languages{f(EsField)}#12, language_code{r}#23, language_name{f(KeywordEsField)}#24],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected index 438c1c6d34382..dcc47c1a23fed 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testLookupJoinOnDataNode/physical_optimization.expected @@ -1,10 +1,10 @@ -TopNExec[[Order[emp_no{f}#0,ASC,LAST]],20[INTEGER],null] -\_ExchangeExec[[avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#0, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24],false] +TopNExec[[Order[emp_no{f(EsField)}#0,ASC,LAST]],20[INTEGER],null] +\_ExchangeExec[[avg_worked_seconds{f(EsField)}#1, birth_date{f(DateEsField)}#2, emp_no{f(EsField)}#0, first_name{f(KeywordEsField)}#3, gender{f(KeywordEsField)}#4, height{f(EsField)}#5, height.float{f(EsField)}#6, height.half_float{f(EsField)}#7, height.scaled_float{f(EsField)}#8, hire_date{f(DateEsField)}#9, is_rehired{f(EsField)}#10, job_positions{f(KeywordEsField)}#11, languages{f(EsField)}#12, languages.byte{f(EsField)}#13, languages.long{f(EsField)}#14, languages.short{f(EsField)}#15, last_name{f(KeywordEsField)}#16, salary{f(EsField)}#17, salary_change{f(EsField)}#18, salary_change.int{f(EsField)}#19, salary_change.keyword{f(KeywordEsField)}#20, salary_change.long{f(EsField)}#21, still_hired{f(EsField)}#22, language_code{r}#23, language_name{f(KeywordEsField)}#24],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#0, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22, language_code{r}#23, language_name{f}#24]] -\_TopN[[Order[emp_no{f}#0,ASC,LAST]],20[INTEGER],false] - \_Join[LEFT,[language_code{r}#23],[language_code{f}#25],null] - |_Eval[[languages{f}#12 AS language_code#23]] +Project[[avg_worked_seconds{f(EsField)}#1, birth_date{f(DateEsField)}#2, emp_no{f(EsField)}#0, first_name{f(KeywordEsField)}#3, gender{f(KeywordEsField)}#4, height{f(EsField)}#5, height.float{f(EsField)}#6, height.half_float{f(EsField)}#7, height.scaled_float{f(EsField)}#8, hire_date{f(DateEsField)}#9, is_rehired{f(EsField)}#10, job_positions{f(KeywordEsField)}#11, languages{f(EsField)}#12, languages.byte{f(EsField)}#13, languages.long{f(EsField)}#14, languages.short{f(EsField)}#15, last_name{f(KeywordEsField)}#16, salary{f(EsField)}#17, salary_change{f(EsField)}#18, salary_change.int{f(EsField)}#19, salary_change.keyword{f(KeywordEsField)}#20, salary_change.long{f(EsField)}#21, still_hired{f(EsField)}#22, language_code{r}#23, language_name{f(KeywordEsField)}#24]] +\_TopN[[Order[emp_no{f(EsField)}#0,ASC,LAST]],20[INTEGER],false] + \_Join[LEFT,[language_code{r}#23],[language_code{f(EsField)}#25],null] + |_Eval[[languages{f(EsField)}#12 AS language_code#23]] | \_Filter[emp_no{f}#0 >= 10091[INTEGER] AND emp_no{f}#0 < 10094[INTEGER]] | \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#0, first_name{f}#3, gender{f}#4, height{f}#5, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22] \_EsRelation[languages_lookup][LOOKUP][language_code{f}#25, language_name{f}#24]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected index 1c5150bf358d7..2884306aee63d 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1, height{f}#2],false] -\_ProjectExec[[_doc{f}#0, hire_date{f}#1, height{f}#2]] +ExchangeSinkExec[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1, height{f(EsField)}#2],false] +\_ProjectExec[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1, height{f(EsField)}#2]] \_FieldExtractExec[hire_date{f}#1, height{f}#2]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST], FieldSort[field=height{f}#2, direction=ASC, nulls=LAST]]] estimatedRowSize[32] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected index 494a0526f6dd3..1807a5e20b15b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1, height{f}#2],false] +ExchangeSinkExec[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1, height{f(EsField)}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#0, hire_date{f}#1, height{f}#2]] -\_TopN[[Order[hire_date{f}#1,ASC,LAST], Order[height{f}#2,ASC,LAST]],20[INTEGER],false] +Project[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1, height{f(EsField)}#2]] +\_TopN[[Order[hire_date{f(DateEsField)}#1,ASC,LAST], Order[height{f(EsField)}#2,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#2, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#1, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected index ab96def3b448c..c9edf368a9a02 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2],false] -\_ProjectExec[[emp_no{f}#0, height{f}#1, hire_date{f}#2]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1, hire_date{f(DateEsField)}#2],false] +\_ProjectExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1, hire_date{f(DateEsField)}#2]] \_FieldExtractExec[emp_no{f}#0]<[],[]> - \_TopNExec[[Order[hire_date{f}#2,ASC,LAST], Order[height{f}#1,ASC,LAST]],20[INTEGER],40] - \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#2, height{f}#1],false] \ No newline at end of file + \_TopNExec[[Order[hire_date{f(DateEsField)}#2,ASC,LAST], Order[height{f(EsField)}#1,ASC,LAST]],20[INTEGER],40] + \_ExchangeSourceExec[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#2, height{f(EsField)}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected index 64df823ba0bbf..c2f87bb079ce4 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleFieldSortTopN/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[hire_date{f}#0, emp_no{f}#1, height{f}#2]] -\_TopNExec[[Order[hire_date{f}#0,ASC,LAST], Order[height{f}#2,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}#1, height{f}#2, hire_date{f}#0],false] +ProjectExec[[hire_date{f(DateEsField)}#0, emp_no{f(EsField)}#1, height{f(EsField)}#2]] +\_TopNExec[[Order[hire_date{f(DateEsField)}#0,ASC,LAST], Order[height{f(EsField)}#2,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f(EsField)}#1, height{f(EsField)}#2, hire_date{f(DateEsField)}#0],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#1, height{f}#2, hire_date{f}#0]] -\_TopN[[Order[hire_date{f}#0,ASC,LAST], Order[height{f}#2,ASC,LAST]],20[INTEGER],false] +Project[[emp_no{f(EsField)}#1, height{f(EsField)}#2, hire_date{f(DateEsField)}#0]] +\_TopN[[Order[hire_date{f(DateEsField)}#0,ASC,LAST], Order[height{f(EsField)}#2,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#1, first_name{f}#5, gender{f}#6, height{f}#2, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#0, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected index fb387032f3d2a..7670a902dd6e9 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] -\_ProjectExec[[_doc{f}#0, hire_date{f}#1]] +ExchangeSinkExec[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1],false] +\_ProjectExec[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1]] \_FieldExtractExec[hire_date{f}#1]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected index 9db0da8910f5b..cfbde5a0c88b3 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] +ExchangeSinkExec[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#0, hire_date{f}#1]] -\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] +Project[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#1, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected index 4b4fc0c891ac1..b4351eb176c15 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] +\_ProjectExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2]] \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> - \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file + \_TopNExec[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected index 92cf16635a7dc..8cf112d600609 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMultipleTopN/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] -\_TopNExec[[Order[salary{f}#1,ASC,LAST]],10[INTEGER],null] - \_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] +ProjectExec[[hire_date{f(DateEsField)}#0, salary{f(EsField)}#1, emp_no{f(EsField)}#2]] +\_TopNExec[[Order[salary{f(EsField)}#1,ASC,LAST]],10[INTEGER],null] + \_TopNExec[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] -\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] +Project[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected index f0d827b7d0c99..17985e6fc7ff0 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,7 +1,7 @@ -ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2]] - \_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] - \_MvExpandExec[job_positions{f}#3,job_positions{r}#1] - \_ProjectExec[[emp_no{f}#0, job_positions{f}#3, salary{f}#2]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2],false] +\_ProjectExec[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2]] + \_TopNExec[[Order[salary{f(EsField)}#2,ASC,LAST]],20[INTEGER],58] + \_MvExpandExec[job_positions{f(KeywordEsField)}#3,job_positions{r}#1] + \_ProjectExec[[emp_no{f(EsField)}#0, job_positions{f(KeywordEsField)}#3, salary{f(EsField)}#2]] \_FieldExtractExec[emp_no{f}#0, job_positions{f}#3, salary{f}#2]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#4], limit[], sort[] estimatedRowSize[62] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected index a9639e399dec8..5932932aa8946 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_physical_optimization_reduce_driver.expected @@ -1,3 +1,3 @@ -ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] -\_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] - \_ExchangeSourceExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2],false] +\_TopNExec[[Order[salary{f(EsField)}#2,ASC,LAST]],20[INTEGER],58] + \_ExchangeSourceExec[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected index baf5e66932990..5f94092df9787 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_data_driver.expected @@ -1,7 +1,7 @@ -ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] +ExchangeSinkExec[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#0, job_positions{r}#1, salary{f}#2]] -\_TopN[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],false] - \_MvExpand[job_positions{f}#3,job_positions{r}#1] - \_Project[[emp_no{f}#0, job_positions{f}#3, salary{f}#2]] +Project[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2]] +\_TopN[[Order[salary{f(EsField)}#2,ASC,LAST]],20[INTEGER],false] + \_MvExpand[job_positions{f(KeywordEsField)}#3,job_positions{r}#1] + \_Project[[emp_no{f(EsField)}#0, job_positions{f(KeywordEsField)}#3, salary{f(EsField)}#2]] \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#0, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#3, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#2, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected index a9639e399dec8..5932932aa8946 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/local_reduce_planned_reduce_driver.expected @@ -1,3 +1,3 @@ -ExchangeSinkExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] -\_TopNExec[[Order[salary{f}#2,ASC,LAST]],20[INTEGER],58] - \_ExchangeSourceExec[[emp_no{f}#0, job_positions{r}#1, salary{f}#2],false] \ No newline at end of file +ExchangeSinkExec[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2],false] +\_TopNExec[[Order[salary{f(EsField)}#2,ASC,LAST]],20[INTEGER],58] + \_ExchangeSourceExec[[emp_no{f(EsField)}#0, job_positions{r}#1, salary{f(EsField)}#2],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected index 7bd205fddb3bd..5f66a7ee4c49f 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testMvExpandBeforeTopN/physical_optimization.expected @@ -1,8 +1,8 @@ -TopNExec[[Order[salary{f}#0,ASC,LAST]],20[INTEGER],null] -\_ExchangeExec[[emp_no{f}#1, job_positions{r}#2, salary{f}#0],false] +TopNExec[[Order[salary{f(EsField)}#0,ASC,LAST]],20[INTEGER],null] +\_ExchangeExec[[emp_no{f(EsField)}#1, job_positions{r}#2, salary{f(EsField)}#0],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#1, job_positions{r}#2, salary{f}#0]] -\_TopN[[Order[salary{f}#0,ASC,LAST]],20[INTEGER],false] - \_MvExpand[job_positions{f}#3,job_positions{r}#2] - \_Project[[emp_no{f}#1, job_positions{f}#3, salary{f}#0]] +Project[[emp_no{f(EsField)}#1, job_positions{r}#2, salary{f(EsField)}#0]] +\_TopN[[Order[salary{f(EsField)}#0,ASC,LAST]],20[INTEGER],false] + \_MvExpand[job_positions{f(KeywordEsField)}#3,job_positions{r}#2] + \_Project[[emp_no{f(EsField)}#1, job_positions{f(KeywordEsField)}#3, salary{f(EsField)}#0]] \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#1, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#3, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#0, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected index d345864f4bcb2..a4298a6c3a196 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[_doc{f}#0, height{f}#1],false] -\_ProjectExec[[_doc{f}#0, height{f}#1]] +ExchangeSinkExec[[_doc{f(EsField)}#0, height{f(EsField)}#1],false] +\_ProjectExec[[_doc{f(EsField)}#0, height{f(EsField)}#1]] \_FieldExtractExec[height{f}#1]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[20], sort[[FieldSort[field=height{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected index 8abcf07553c66..5ceaff6ed3ace 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}#0, height{f}#1],false] +ExchangeSinkExec[[_doc{f(EsField)}#0, height{f(EsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#0, height{f}#1]] -\_TopN[[Order[height{f}#1,ASC,LAST]],20[INTEGER],false] +Project[[_doc{f(EsField)}#0, height{f(EsField)}#1]] +\_TopN[[Order[height{f(EsField)}#1,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#1, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected index 3425364e715c1..3633dfb6c48db 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, height{f}#1],false] -\_ProjectExec[[emp_no{f}#0, height{f}#1]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1],false] +\_ProjectExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1]] \_FieldExtractExec[emp_no{f}#0]<[],[]> - \_TopNExec[[Order[height{f}#1,ASC,LAST]],20[INTEGER],32] - \_ExchangeSourceExec[[_doc{f}#2, height{f}#1],false] \ No newline at end of file + \_TopNExec[[Order[height{f(EsField)}#1,ASC,LAST]],20[INTEGER],32] + \_ExchangeSourceExec[[_doc{f(EsField)}#2, height{f(EsField)}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected index e659e9ce08d64..66a0e8e8c2995 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testPushedDownTopN/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[emp_no{f}#0, height{f}#1]] -\_TopNExec[[Order[height{f}#1,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}#0, height{f}#1],false] +ProjectExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1]] +\_TopNExec[[Order[height{f(EsField)}#1,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f(EsField)}#0, height{f(EsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#0, height{f}#1]] -\_TopN[[Order[height{f}#1,ASC,LAST]],20[INTEGER],false] +Project[[emp_no{f(EsField)}#0, height{f(EsField)}#1]] +\_TopN[[Order[height{f(EsField)}#1,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#0, first_name{f}#4, gender{f}#5, height{f}#1, height.float{f}#6, height.half_float{f}#7, height.scaled_float{f}#8, hire_date{f}#9, is_rehired{f}#10, job_positions{f}#11, languages{f}#12, languages.byte{f}#13, languages.long{f}#14, languages.short{f}#15, last_name{f}#16, salary{f}#17, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected index 2022c5678fda7..f7ddf114fbf31 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_physical_optimization_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}#0, salary{f}#1, hire_date{f}#2],false] -\_ProjectExec[[_doc{f}#0, salary{f}#1, hire_date{f}#2]] +ExchangeSinkExec[[_doc{f(EsField)}#0, salary{f(EsField)}#1, hire_date{f(DateEsField)}#2],false] +\_ProjectExec[[_doc{f(EsField)}#0, salary{f(EsField)}#1, hire_date{f(DateEsField)}#2]] \_FieldExtractExec[salary{f}#1, hire_date{f}#2]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[20], sort[[FieldSort[field=hire_date{f}#2, direction=ASC, nulls=LAST]]] estimatedRowSize[28] queryBuilderAndTags [[QueryBuilderAndTags[query={ "esql_single_value" : { diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected index a3bf3dbd30194..36d2a8769026a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_data_driver.expected @@ -1,6 +1,6 @@ -ExchangeSinkExec[[_doc{f}#0, salary{f}#1, hire_date{f}#2],false] +ExchangeSinkExec[[_doc{f(EsField)}#0, salary{f(EsField)}#1, hire_date{f(DateEsField)}#2],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#0, salary{f}#1, hire_date{f}#2]] -\_TopN[[Order[hire_date{f}#2,ASC,LAST]],20[INTEGER],false] +Project[[_doc{f(EsField)}#0, salary{f(EsField)}#1, hire_date{f(DateEsField)}#2]] +\_TopN[[Order[hire_date{f(DateEsField)}#2,ASC,LAST]],20[INTEGER],false] \_Filter[salary{f}#1 > 10000[INTEGER]] \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#2, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#1, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected index 178d31ccc5dc1..22b9264fc278a 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] +\_ProjectExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2]] \_FieldExtractExec[emp_no{f}#0]<[],[]> - \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#3, salary{f}#2, hire_date{f}#1],false] \ No newline at end of file + \_TopNExec[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f(EsField)}#3, salary{f(EsField)}#2, hire_date{f(DateEsField)}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected index 6fc12a53e3980..4b4f50ecdb071 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testSomeFieldsNeededBeforeLateMaterialization/physical_optimization.expected @@ -1,8 +1,8 @@ -ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] -\_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] +ProjectExec[[hire_date{f(DateEsField)}#0, salary{f(EsField)}#1, emp_no{f(EsField)}#2]] +\_TopNExec[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] -\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] +Project[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],false] \_Filter[salary{f}#1 > 10000[INTEGER]] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected index fb387032f3d2a..7670a902dd6e9 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] -\_ProjectExec[[_doc{f}#0, hire_date{f}#1]] +ExchangeSinkExec[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1],false] +\_ProjectExec[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1]] \_FieldExtractExec[hire_date{f}#1]<[],[]> \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[20], sort[[FieldSort[field=hire_date{f}#1, direction=ASC, nulls=LAST]]] estimatedRowSize[24] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected index 9db0da8910f5b..cfbde5a0c88b3 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] +ExchangeSinkExec[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#0, hire_date{f}#1]] -\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] +Project[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#1, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected index 3c81025a6c14e..a0f7bfca2eddb 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[hire_date{f}#0, salary{f}#1],false] -\_ProjectExec[[hire_date{f}#0, salary{f}#1]] +ExchangeSinkExec[[hire_date{f(DateEsField)}#0, salary{f(EsField)}#1],false] +\_ProjectExec[[hire_date{f(DateEsField)}#0, salary{f(EsField)}#1]] \_FieldExtractExec[salary{f}#1]<[],[]> - \_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],32] - \_ExchangeSourceExec[[_doc{f}#2, hire_date{f}#0],false] \ No newline at end of file + \_TopNExec[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],32] + \_ExchangeSourceExec[[_doc{f(EsField)}#2, hire_date{f(DateEsField)}#0],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected index d520dec0664bd..9aac8fbe309dd 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNThenStats/physical_optimization.expected @@ -1,10 +1,10 @@ ProjectExec[[avg_salary{r}#0, count{r}#1]] \_EvalExec[[$$SUM$avg_salary$0{r$}#2 / $$COUNT$avg_salary$1{r$}#3 AS avg_salary#0]] \_LimitExec[10000[INTEGER],null] - \_AggregateExec[[],[SUM(salary{f}#4,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS $$SUM$avg_salary$0#2, COUNT(salary{f}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS $$COUNT$avg_salary$1#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count#1],SINGLE,[$$SUM$avg_salary$0$sum{r}#5, $$SUM$avg_salary$0$seen{r}#6, $$COUNT$avg_salary$1$count{r}#7, $$COUNT$avg_salary$1$seen{r}#8, $$count$count{r}#9, $$count$seen{r}#10],null] - \_TopNExec[[Order[hire_date{f}#11,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[hire_date{f}#11, salary{f}#4],false] + \_AggregateExec[[],[SUM(salary{f(EsField)}#4,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS $$SUM$avg_salary$0#2, COUNT(salary{f(EsField)}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS $$COUNT$avg_salary$1#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count#1],SINGLE,[$$SUM$avg_salary$0$sum{r}#5, $$SUM$avg_salary$0$seen{r}#6, $$COUNT$avg_salary$1$count{r}#7, $$COUNT$avg_salary$1$seen{r}#8, $$count$count{r}#9, $$count$seen{r}#10],null] + \_TopNExec[[Order[hire_date{f(DateEsField)}#11,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[hire_date{f(DateEsField)}#11, salary{f(EsField)}#4],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[hire_date{f}#11, salary{f}#4]] -\_TopN[[Order[hire_date{f}#11,ASC,LAST]],20[INTEGER],false] +Project[[hire_date{f(DateEsField)}#11, salary{f(EsField)}#4]] +\_TopN[[Order[hire_date{f(DateEsField)}#11,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][avg_worked_seconds{f}#12, birth_date{f}#13, emp_no{f}#14, first_name{f}#15, gender{f}#16, height{f}#17, height.float{f}#18, height.half_float{f}#19, height.scaled_float{f}#20, hire_date{f}#11, is_rehired{f}#21, job_positions{f}#22, languages{f}#23, languages.byte{f}#24, languages.long{f}#25, languages.short{f}#26, last_name{f}#27, salary{f}#4, salary_change{f}#28, salary_change.int{f}#29, salary_change.keyword{f}#30, salary_change.long{f}#31, still_hired{f}#32]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected index 80a4e9f155b81..24764dc20073b 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_physical_optimization_data_driver.expected @@ -1,4 +1,4 @@ -ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] -\_ProjectExec[[_doc{f}#0, hire_date{r}#1]] +ExchangeSinkExec[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1],false] +\_ProjectExec[[_doc{f(EsField)}#0, hire_date{r}#1]] \_EvalExec[[null[DATETIME] AS hire_date#1]] \_EsQueryExec[employees], indexMode[standard], [_doc{f}#0], limit[20], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected index 9db0da8910f5b..cfbde5a0c88b3 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_data_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[_doc{f}#0, hire_date{f}#1],false] +ExchangeSinkExec[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[_doc{f}#0, hire_date{f}#1]] -\_TopN[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],false] +Project[[_doc{f(EsField)}#0, hire_date{f(DateEsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][_doc{f}#0, avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#1, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected index 4b4fc0c891ac1..b4351eb176c15 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/local_reduce_planned_reduce_driver.expected @@ -1,5 +1,5 @@ -ExchangeSinkExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2],false] -\_ProjectExec[[emp_no{f}#0, hire_date{f}#1, salary{f}#2]] +ExchangeSinkExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2],false] +\_ProjectExec[[emp_no{f(EsField)}#0, hire_date{f(DateEsField)}#1, salary{f(EsField)}#2]] \_FieldExtractExec[emp_no{f}#0, salary{f}#2]<[],[]> - \_TopNExec[[Order[hire_date{f}#1,ASC,LAST]],20[INTEGER],36] - \_ExchangeSourceExec[[_doc{f}#3, hire_date{f}#1],false] \ No newline at end of file + \_TopNExec[[Order[hire_date{f(DateEsField)}#1,ASC,LAST]],20[INTEGER],36] + \_ExchangeSourceExec[[_doc{f(EsField)}#3, hire_date{f(DateEsField)}#1],false] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected index 84b502cae4e25..fac7b0beb280e 100644 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/plugin/golden_tests/LateMaterializationPlannerGoldenTests/testTopNWithMissingSortField/physical_optimization.expected @@ -1,7 +1,7 @@ -ProjectExec[[hire_date{f}#0, salary{f}#1, emp_no{f}#2]] -\_TopNExec[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],null] - \_ExchangeExec[[emp_no{f}#2, hire_date{f}#0, salary{f}#1],false] +ProjectExec[[hire_date{f(DateEsField)}#0, salary{f(EsField)}#1, emp_no{f(EsField)}#2]] +\_TopNExec[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],null] + \_ExchangeExec[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1],false] \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[emp_no{f}#2, hire_date{f}#0, salary{f}#1]] -\_TopN[[Order[hire_date{f}#0,ASC,LAST]],20[INTEGER],false] +Project[[emp_no{f(EsField)}#2, hire_date{f(DateEsField)}#0, salary{f(EsField)}#1]] +\_TopN[[Order[hire_date{f(DateEsField)}#0,ASC,LAST]],20[INTEGER],false] \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#0, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#1, salary_change{f}#18, salary_change.int{f}#19, salary_change.keyword{f}#20, salary_change.long{f}#21, still_hired{f}#22]<>]] \ No newline at end of file diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/apps.csv b/x-pack/plugin/sql/qa/server/src/main/resources/apps.csv index 9bd4123424f02..7fefd7bfb316f 100644 --- a/x-pack/plugin/sql/qa/server/src/main/resources/apps.csv +++ b/x-pack/plugin/sql/qa/server/src/main/resources/apps.csv @@ -1,4 +1,4 @@ -id,version,name +id,version2,name 1,1,aaaaa 2,2.1,bbbbb 3,2.3.4,ccccc From 4b44c194069ee91edfe2b76e5ca697e816edc4cf Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 4 Mar 2026 11:59:23 +0200 Subject: [PATCH 090/137] Extract common Pushdown and Analyzer golden test code --- .../analysis/AnalyzerUnmappedGoldenTests.java | 51 ++-------------- .../esql/optimizer/PushdownGoldenTests.java | 8 +-- .../optimizer/UnmappedGoldenTestCase.java | 61 +++++++++++++++++++ 3 files changed, 67 insertions(+), 53 deletions(-) create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/UnmappedGoldenTestCase.java diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java index 493bbc4d70d63..822eefb6e9a43 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -8,16 +8,15 @@ package org.elasticsearch.xpack.esql.analysis; import org.elasticsearch.xpack.esql.action.EsqlCapabilities; -import org.elasticsearch.xpack.esql.optimizer.GoldenTestCase; +import org.elasticsearch.xpack.esql.optimizer.UnmappedGoldenTestCase; import java.util.EnumSet; -import java.util.Optional; /** * Golden tests for analyzer behavior with unmapped fields using SET unmapped_fields="nullify" and "load". * These tests verify that unmapped fields are properly handled. */ -public class AnalyzerUnmappedGoldenTests extends GoldenTestCase { +public class AnalyzerUnmappedGoldenTests extends UnmappedGoldenTestCase { private static final EnumSet STAGES = EnumSet.of(Stage.ANALYSIS); public void testKeep() throws Exception { @@ -391,7 +390,7 @@ public void testTimeSeriesRateUnmapped() throws Exception { runTestsNullifyOnly(""" TS k8s | STATS r = RATE(does_not_exist) BY tbucket(1 hour) - """); + """, STAGES); } public void testTimeSeriesFirstOverTimeUnmapped() throws Exception { @@ -443,49 +442,7 @@ public void testDifferentTypesAndUnmappedCast() throws Exception { """); } - private static String setUnmappedNullify(String query) { - return "SET unmapped_fields=\"nullify\"; " + query; - } - - private static String setUnmappedLoad(String query) { - return "SET unmapped_fields=\"load\"; " + query; - } - private void runTests(String query) { - var nullifyException = tryRunTestsNullifyOnly(query); - var loadException = tryRunTestsLoadOnly(query); - if (nullifyException.isPresent() && loadException.isPresent()) { - throw new AssertionError("Both nullify and load modes failed", nullifyException.get()); - } else if (nullifyException.isPresent()) { - throw new AssertionError("Nullify mode failed (but load succeeded)", nullifyException.get()); - } else if (loadException.isPresent()) { - throw new AssertionError("Load mode failed (but nullify succeeded)", loadException.get()); - } - } - - private void runTestsNullifyOnly(String query) { - var nullifyException = tryRunTestsNullifyOnly(query); - if (nullifyException.isPresent()) { - throw new RuntimeException("Nullify mode failed", nullifyException.get()); - } - } - - private Optional tryRunTestsNullifyOnly(String query) { - return EsqlCapabilities.Cap.OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW.isEnabled() - ? builder(setUnmappedNullify(query)).nestedPath("nullify").stages(STAGES).tryRun() - : Optional.empty(); - } - - private void runTestsLoadOnly(String query) { - var loadException = tryRunTestsLoadOnly(query); - if (loadException.isPresent()) { - throw new RuntimeException("Load mode failed", loadException.get()); - } - } - - private Optional tryRunTestsLoadOnly(String query) { - return EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled() - ? builder(setUnmappedLoad(query)).nestedPath("load").stages(STAGES).tryRun() - : Optional.empty(); + runTestsNullifyAndLoad(query, STAGES); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java index 0a40ac6df2600..b487b1a9f05ee 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PushdownGoldenTests.java @@ -7,15 +7,13 @@ package org.elasticsearch.xpack.esql.optimizer; -import org.elasticsearch.xpack.esql.action.EsqlCapabilities; - import java.util.EnumSet; /** * Golden tests for filter and sort pushdown to Lucene. * New pushdown tests should be added here rather than in {@link LocalPhysicalPlanOptimizerTests}. */ -public class PushdownGoldenTests extends GoldenTestCase { +public class PushdownGoldenTests extends UnmappedGoldenTestCase { private static final EnumSet STAGES = EnumSet.of(Stage.LOCAL_PHYSICAL_OPTIMIZATION); public void testFilterPushdownNoUnmapped() { @@ -94,8 +92,6 @@ public void testSortConjunctionPushableAndNonPushable() { } private void runUnmappedTests(String query) { - runGoldenTest("SET unmapped_fields=\"nullify\"; " + query, STAGES, "nullify"); - assumeTrue("Requires OPTIONAL_FIELDS_V2 for load", EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled()); - runGoldenTest("SET unmapped_fields=\"load\"; " + query, STAGES, "load"); + runTestsNullifyAndLoad(query, STAGES); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/UnmappedGoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/UnmappedGoldenTestCase.java new file mode 100644 index 0000000000000..d15bad64dfdb5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/UnmappedGoldenTestCase.java @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.optimizer; + +import org.elasticsearch.xpack.esql.action.EsqlCapabilities; + +import java.util.EnumSet; +import java.util.Optional; + +/** Base for golden tests that run with both unmapped_fields=nullify and unmapped_fields=load. */ +public abstract class UnmappedGoldenTestCase extends GoldenTestCase { + /** Runs the query with both {@code NULLIFY} and {@code LOAD}; throws if either fails. */ + protected void runTestsNullifyAndLoad(String query, EnumSet stages) { + Optional nullifyException = tryRunTestsNullifyOnly(query, stages); + Optional loadException = tryRunTestsLoadOnly(query, stages); + nullifyException.ifPresent(e -> { + throw new RuntimeException( + loadException.isPresent() ? "Both nullify and load modes failed" : "Nullify mode failed (but load succeeded)", + e + ); + }); + loadException.ifPresent(e -> { + throw new RuntimeException("Load mode failed (but nullify succeeded)", e); + }); + } + + protected void runTestsNullifyOnly(String query, EnumSet stages) { + tryRunTestsNullifyOnly(query, stages).ifPresent(e -> { + throw new RuntimeException("Nullify mode failed", e); + }); + } + + protected void runTestsLoadOnly(String query, EnumSet stages) { + tryRunTestsLoadOnly(query, stages).ifPresent(e -> { + throw new RuntimeException("Load mode failed", e); + }); + } + + private Optional tryRunTestsNullifyOnly(String query, EnumSet stages) { + return builder(setUnmappedNullify(query)).nestedPath("nullify").stages(stages).tryRun(); + } + + private Optional tryRunTestsLoadOnly(String query, EnumSet stages) { + return EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled() + ? builder(setUnmappedLoad(query)).nestedPath("load").stages(stages).tryRun() + : Optional.empty(); + } + + private static String setUnmappedNullify(String query) { + return "SET unmapped_fields=\"nullify\"; " + query; + } + + private static String setUnmappedLoad(String query) { + return "SET unmapped_fields=\"load\"; " + query; + } +} From af189e8c61c56bb122dc25c6b25b8991ef438c45 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 4 Mar 2026 12:51:18 +0200 Subject: [PATCH 091/137] Remove tests covered by golden tests --- .../esql/analysis/AnalyzerUnmappedTests.java | 1360 ++--------------- 1 file changed, 122 insertions(+), 1238 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index 18704cc4a981b..ca8efd6f2fd09 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -71,66 +71,6 @@ // @TestLogging(value = "org.elasticsearch.xpack.esql:TRACE", reason = "debug") public class AnalyzerUnmappedTests extends ESTestCase { - /* - * Limit[1000[INTEGER],false,false] - * \_Project[[does_not_exist_field{r}#16]] - * \_Eval[[null[NULL] AS does_not_exist_field#16]] - * \_EsRelation[test][_meta_field{f}#11, emp_no{f}#5, first_name{f}#6, ge..] - */ - public void testKeep() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | KEEP does_not_exist_field - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var project = as(limit.child(), Project.class); - assertThat(project.projections(), hasSize(1)); - assertThat(Expressions.name(project.projections().getFirst()), is("does_not_exist_field")); - - var eval = as(project.child(), Eval.class); - assertThat(eval.fields(), hasSize(1)); - var alias = as(eval.fields().getFirst(), Alias.class); - assertThat(alias.name(), is("does_not_exist_field")); - var literal = as(alias.child(), Literal.class); - assertThat(literal.dataType(), is(DataType.NULL)); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Project[[does_not_exist_field{r}#18]] - * \_Eval[[null[NULL] AS does_not_exist_field#17]] - * \_EsRelation[test][_meta_field{f}#12, emp_no{f}#6, first_name{f}#7, ge..] - */ - public void testKeepRepeated() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | KEEP does_not_exist_field, does_not_exist_field - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var project = as(limit.child(), Project.class); - assertThat(project.projections(), hasSize(1)); - assertThat(Expressions.name(project.projections().getFirst()), is("does_not_exist_field")); - - var eval = as(project.child(), Eval.class); - assertThat(eval.fields(), hasSize(1)); - var alias = as(eval.fields().getFirst(), Alias.class); - assertThat(alias.name(), is("does_not_exist_field")); - var literal = as(alias.child(), Literal.class); - assertThat(literal.dataType(), is(DataType.NULL)); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - public void testFailKeepAndNonMatchingStar() { var query = """ FROM test @@ -141,70 +81,6 @@ public void testFailKeepAndNonMatchingStar() { verificationFailure(setUnmappedLoad(query), failure); } - /* - * Limit[1000[INTEGER],false,false] - * \_Project[[emp_no{f}#6, does_not_exist_field{r}#18]] - * \_Eval[[null[NULL] AS does_not_exist_field#18]] - * \_EsRelation[test][_meta_field{f}#12, emp_no{f}#6, first_name{f}#7, ge..] - */ - public void testKeepAndMatchingStar() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | KEEP emp_*, does_not_exist_field - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var project = as(limit.child(), Project.class); - assertThat(project.projections(), hasSize(2)); - assertThat(Expressions.names(project.projections()), is(List.of("emp_no", "does_not_exist_field"))); - - var eval = as(project.child(), Eval.class); - assertThat(eval.fields(), hasSize(1)); - var alias = as(eval.fields().getFirst(), Alias.class); - assertThat(alias.name(), is("does_not_exist_field")); - var literal = as(alias.child(), Literal.class); - assertThat(literal.dataType(), is(DataType.NULL)); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Project[[does_not_exist_field1{r}#20, does_not_exist_field2{r}#22]] - * \_Eval[[TOINTEGER(does_not_exist_field1{r}#20) + 42[INTEGER] AS x#5]] - * \_Eval[[null[NULL] AS does_not_exist_field1#20, null[NULL] AS does_not_exist_field2#22]] - * \_EsRelation[test][_meta_field{f}#15, emp_no{f}#9, first_name{f}#10, g..] - */ - public void testEvalAndKeep() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | EVAL x = does_not_exist_field1::INTEGER + 42 - | KEEP does_not_exist_field1, does_not_exist_field2 - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var project = as(limit.child(), Project.class); - assertThat(project.projections(), hasSize(2)); - assertThat(Expressions.names(project.projections()), is(List.of("does_not_exist_field1", "does_not_exist_field2"))); - - var eval1 = as(project.child(), Eval.class); - assertThat(eval1.fields(), hasSize(1)); - var aliasX = as(eval1.fields().getFirst(), Alias.class); - assertThat(aliasX.name(), is("x")); - assertThat(Expressions.name(aliasX.child()), is("does_not_exist_field1::INTEGER + 42")); - - var eval2 = as(eval1.child(), Eval.class); - assertThat(Expressions.names(eval2.fields()), is(List.of("does_not_exist_field1", "does_not_exist_field2"))); - - var relation = as(eval2.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - public void testFailKeepAndMatchingAndNonMatchingStar() { var query = """ FROM test @@ -226,187 +102,6 @@ public void testFailAfterKeep() { verificationFailure(setUnmappedLoad(query), failure); } - /* - * Limit[1000[INTEGER],false,false] - * \_Eval[[does_not_exist_field{r}#22 + 2[INTEGER] AS y#9]] - * \_Eval[[emp_no{f}#11 + 1[INTEGER] AS x#6]] - * \_Project[[_meta_field{f}#17, emp_no{f}#11, first_name{f}#12, gender{f}#13, hire_date{f}#18, job{f}#19, job.raw{f}#20, - * languages{f}#14, last_name{f}#15, long_noidx{f}#21, salary{f}#16, does_not_exist_field{r}#22]] - * \_Eval[[null[NULL] AS does_not_exist_field#22]] - * \_EsRelation[test][_meta_field{f}#17, emp_no{f}#11, first_name{f}#12, ..] - */ - public void testEvalAfterKeepStar() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | KEEP * - | EVAL x = emp_no + 1 - | EVAL y = does_not_exist_field + 2 - """)); - - // Top implicit limit 1000 - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - // Eval for y = does_not_exist_field + 2 - var evalY = as(limit.child(), Eval.class); - assertThat(evalY.fields(), hasSize(1)); - assertThat(evalY.fields().get(0).name(), is("y")); - - // The child is Eval for x = emp_no + 1 - var evalX = as(evalY.child(), Eval.class); - assertThat(evalX.fields(), hasSize(1)); - assertThat(evalX.fields().get(0).name(), is("x")); - - // The child is Project with all fields plus does_not_exist_field - var esqlProject = as(evalX.child(), Project.class); - assertThat( - Expressions.names(esqlProject.output()), - is( - List.of( - "_meta_field", - "emp_no", - "first_name", - "gender", - "hire_date", - "job", - "job.raw", - "languages", - "last_name", - "long_noidx", - "salary", - "does_not_exist_field" - ) - ) - ); - - // The child is Eval introducing does_not_exist_field as null - var evalNull = as(esqlProject.child(), Eval.class); - assertThat(evalNull.fields(), hasSize(1)); - var alias = as(evalNull.fields().get(0), Alias.class); - assertThat(alias.name(), is("does_not_exist_field")); - var lit = as(alias.child(), Literal.class); - assertThat(lit.dataType(), is(DataType.NULL)); - - // The child is EsRelation - var relation = as(evalNull.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Eval[[emp_does_not_exist_field{r}#23 + 2[INTEGER] AS y#10]] - * \_Eval[[emp_no{f}#12 + 1[INTEGER] AS x#7]] - * \_Project[[emp_no{f}#12, _meta_field{f}#18, first_name{f}#13, gender{f}#14, hire_date{f}#19, job{f}#20, job.raw{f}#21, - * languages{f}#15, last_name{f}#16, long_noidx{f}#22, salary{f}#17, emp_does_not_exist_field{r}#23]] - * \_Eval[[null[NULL] AS emp_does_not_exist_field#23]] - * \_EsRelation[test][_meta_field{f}#18, emp_no{f}#12, first_name{f}#13, ..] - */ - public void testEvalAfterMatchingKeepWithWildcard() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | KEEP emp_no, * - | EVAL x = emp_no + 1 - | EVAL y = emp_does_not_exist_field + 2 - """)); - - // Top implicit limit 1000 - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - // Eval for y = emp_does_not_exist_field + 2 - var evalY = as(limit.child(), Eval.class); - assertThat(evalY.fields(), hasSize(1)); - assertThat(evalY.fields().get(0).name(), is("y")); - - // The child is Eval for x = emp_no + 1 - var evalX = as(evalY.child(), Eval.class); - assertThat(evalX.fields(), hasSize(1)); - assertThat(evalX.fields().get(0).name(), is("x")); - - // The child is Project with all fields plus emp_does_not_exist_field - var esqlProject = as(evalX.child(), Project.class); - assertThat( - Expressions.names(esqlProject.output()), - is( - List.of( - "emp_no", - "_meta_field", - "first_name", - "gender", - "hire_date", - "job", - "job.raw", - "languages", - "last_name", - "long_noidx", - "salary", - "emp_does_not_exist_field" - ) - ) - ); - - // The child is Eval introducing emp_does_not_exist_field as null - var evalNull = as(esqlProject.child(), Eval.class); - assertThat(evalNull.fields(), hasSize(1)); - var alias = as(evalNull.fields().get(0), Alias.class); - assertThat(alias.name(), is("emp_does_not_exist_field")); - var lit = as(alias.child(), Literal.class); - assertThat(lit.dataType(), is(DataType.NULL)); - - // The child is EsRelation - var relation = as(evalNull.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Project[[_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]] - * \_Eval[[null[NULL] AS does_not_exist_field#17, null[NULL] AS neither_this#18]] - * \_EsRelation[test][_meta_field{f}#12, emp_no{f}#6, first_name{f}#7, ge..] - */ - public void testDrop() { - var extraField = randomFrom("", "does_not_exist_field", "neither_this"); - var hasExtraField = extraField.isEmpty() == false; - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | DROP does_not_exist_field - """ + (hasExtraField ? ", " : "") + extraField)); // add emp_no to avoid "no fields left" case - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var project = as(limit.child(), Project.class); - // All fields from the original relation are projected, as the dropped field did not exist. - assertThat(project.projections(), hasSize(11)); - assertThat( - Expressions.names(project.projections()), - is( - List.of( - "_meta_field", - "emp_no", - "first_name", - "gender", - "hire_date", - "job", - "job.raw", - "languages", - "last_name", - "long_noidx", - "salary" - ) - ) - ); - - var eval = as(project.child(), Eval.class); - var expectedNames = hasExtraField && extraField.equals("does_not_exist_field") == false - ? List.of("does_not_exist_field", extraField) - : List.of("does_not_exist_field"); - assertThat(Expressions.names(eval.fields()), is(expectedNames)); - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - public void testFailDropWithNonMatchingStar() { var query = """ FROM test @@ -417,48 +112,6 @@ public void testFailDropWithNonMatchingStar() { verificationFailure(setUnmappedLoad(query), failure); } - /* - * Limit[1000[INTEGER],false,false] - * \_Project[[_meta_field{f}#12, 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]] - * \_Eval[[null[NULL] AS does_not_exist_field#18]] - * \_EsRelation[test][_meta_field{f}#12, emp_no{f}#6, first_name{f}#7, ge..] - */ - public void testDropWithMatchingStar() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | DROP emp_*, does_not_exist_field - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var project = as(limit.child(), Project.class); - assertThat(project.projections(), hasSize(10)); - assertThat( - Expressions.names(project.projections()), - is( - List.of( - "_meta_field", - "first_name", - "gender", - "hire_date", - "job", - "job.raw", - "languages", - "last_name", - "long_noidx", - "salary" - ) - ) - ); - - var eval = as(project.child(), Eval.class); - assertThat(Expressions.names(eval.fields()), is(List.of("does_not_exist_field"))); - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - public void testFailDropWithMatchingAndNonMatchingStar() { var query = """ FROM test @@ -483,16 +136,16 @@ public void testFailEvalAfterDrop() { /* * Limit[1000[INTEGER],false,false] - * \_Project[[_meta_field{f}#16, emp_no{f}#10 AS employee_number#8, first_name{f}#11, gender{f}#12, hire_date{f}#17, job{f}#18, - * job.raw{f}#19, languages{f}#13, last_name{f}#14, long_noidx{f}#20, salary{f}#15, - * now_it_does#12 AS does_not_exist_field{r}#21]] - * \_Eval[[null[NULL] AS does_not_exist_field#21]] - * \_EsRelation[test][_meta_field{f}#16, emp_no{f}#10, first_name{f}#11, ..] + * \_Project[[_meta_field{f}#19, emp_no{f}#13 AS employee_number#11, first_name{f}#14, gender{f}#15, hire_date{f}#20, + * job{f}#21, job.raw{f}#22, languages{f}#16, last_name{f}#17, long_noidx{f}#23, salary{f}#18, + * neither_does_this{r}#25 AS now_it_does#8]] + * \_Eval[[null[NULL] AS does_not_exist_field#24, null[NULL] AS neither_does_this#25]] + * \_EsRelation[test][_meta_field{f}#19, emp_no{f}#13, first_name{f}#14, ..] */ - public void testRename() { + public void testRenameShadowed() { var plan = analyzeStatement(setUnmappedNullify(""" FROM test - | RENAME does_not_exist_field AS now_it_does, emp_no AS employee_number + | RENAME does_not_exist_field AS now_it_does, neither_does_this AS now_it_does, emp_no AS employee_number """)); var limit = as(plan, Limit.class); @@ -521,263 +174,20 @@ public void testRename() { ); var eval = as(project.child(), Eval.class); - assertThat(eval.fields(), hasSize(1)); + assertThat(eval.fields(), hasSize(2)); var alias = as(eval.fields().getFirst(), Alias.class); assertThat(alias.name(), is("does_not_exist_field")); var literal = as(alias.child(), Literal.class); assertThat(literal.dataType(), is(DataType.NULL)); + alias = as(eval.fields().getLast(), Alias.class); + assertThat(alias.name(), is("neither_does_this")); + literal = as(alias.child(), Literal.class); + assertThat(literal.dataType(), is(DataType.NULL)); var relation = as(eval.child(), EsRelation.class); assertThat(relation.indexPattern(), is("test")); } - /* - * Limit[1000[INTEGER],false,false] - * \_Project[[_meta_field{f}#19, emp_no{f}#13 AS employee_number#11, first_name{f}#14, gender{f}#15, hire_date{f}#20, - * job{f}#21, job.raw{f}#22, languages{f}#16, last_name{f}#17, long_noidx{f}#23, salary{f}#18, - * neither_does_this{r}#25 AS now_it_does#8]] - * \_Eval[[null[NULL] AS does_not_exist_field#24, null[NULL] AS neither_does_this#25]] - * \_EsRelation[test][_meta_field{f}#19, emp_no{f}#13, first_name{f}#14, ..] - */ - public void testRenameShadowed() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | RENAME does_not_exist_field AS now_it_does, neither_does_this AS now_it_does, emp_no AS employee_number - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var project = as(limit.child(), Project.class); - assertThat(project.projections(), hasSize(12)); - assertThat( - Expressions.names(project.projections()), - is( - List.of( - "_meta_field", - "employee_number", - "first_name", - "gender", - "hire_date", - "job", - "job.raw", - "languages", - "last_name", - "long_noidx", - "salary", - "now_it_does" - ) - ) - ); - - var eval = as(project.child(), Eval.class); - assertThat(eval.fields(), hasSize(2)); - var alias = as(eval.fields().getFirst(), Alias.class); - assertThat(alias.name(), is("does_not_exist_field")); - var literal = as(alias.child(), Literal.class); - assertThat(literal.dataType(), is(DataType.NULL)); - alias = as(eval.fields().getLast(), Alias.class); - assertThat(alias.name(), is("neither_does_this")); - literal = as(alias.child(), Literal.class); - assertThat(literal.dataType(), is(DataType.NULL)); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Eval[[does_not_exist{r}#21 + 1[INTEGER] AS x#8]] - * \_Project[[_meta_field{f}#16, emp_no{f}#10 AS employee_number#5, first_name{f}#11, gender{f}#12, hire_date{f}#17, job{f}#18, - * job.raw{f}#19, languages{f}#13, last_name{f}#14, long_noidx{f}#20, salary{f}#15, does_not_exist{r}#21]] - * \_Eval[[null[NULL] AS does_not_exist#21]] - * \_EsRelation[test][_meta_field{f}#16, emp_no{f}#10, first_name{f}#11, ..] - */ - public void testEvalAfterRename() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | RENAME emp_no AS employee_number - | EVAL x = does_not_exist + 1 - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var eval = as(limit.child(), Eval.class); - assertThat(eval.fields(), hasSize(1)); - assertThat(eval.fields().get(0).name(), is("x")); - assertThat( - Expressions.names(eval.output()), - is( - List.of( - "_meta_field", - "employee_number", - "first_name", - "gender", - "hire_date", - "job", - "job.raw", - "languages", - "last_name", - "long_noidx", - "salary", - "does_not_exist", - "x" - ) - ) - ); - - var esqlProject = as(eval.child(), Project.class); - assertThat( - Expressions.names(esqlProject.output()), - is( - List.of( - "_meta_field", - "employee_number", - "first_name", - "gender", - "hire_date", - "job", - "job.raw", - "languages", - "last_name", - "long_noidx", - "salary", - "does_not_exist" - ) - ) - ); - - var evalNull = as(esqlProject.child(), Eval.class); - assertThat(evalNull.fields(), hasSize(1)); - var alias = as(evalNull.fields().get(0), Alias.class); - assertThat(alias.name(), is("does_not_exist")); - var lit = as(alias.child(), Literal.class); - assertThat(lit.dataType(), is(DataType.NULL)); - - var relation = as(evalNull.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Eval[[does_not_exist_field{r}#18 + 1[INTEGER] AS x#5]] - * \_Eval[[null[NULL] AS does_not_exist_field#18]] - * \_EsRelation[test][_meta_field{f}#13, emp_no{f}#7, first_name{f}#8, ge..] - */ - public void testEval() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | EVAL x = does_not_exist_field + 1 - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var outerEval = as(limit.child(), Eval.class); - assertThat(outerEval.fields(), hasSize(1)); - var aliasX = as(outerEval.fields().getFirst(), Alias.class); - assertThat(aliasX.name(), is("x")); - assertThat(Expressions.name(aliasX.child()), is("does_not_exist_field + 1")); - - var innerEval = as(outerEval.child(), Eval.class); - assertThat(innerEval.fields(), hasSize(1)); - var aliasField = as(innerEval.fields().getFirst(), Alias.class); - assertThat(aliasField.name(), is("does_not_exist_field")); - var literal = as(aliasField.child(), Literal.class); - assertThat(literal.dataType(), is(DataType.NULL)); - - var relation = as(innerEval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Eval[[b{r}#25 + c{r}#27 AS y#12]] - * \_Eval[[a{r}#4 + b{r}#25 AS x#8]] - * \_Eval[[1[INTEGER] AS a#4, null[NULL] AS b#25, null[NULL] AS c#27]] - * \_EsRelation[test][_meta_field{f}#20, emp_no{f}#14, first_name{f}#15, ..] - */ - public void testMultipleEvaled() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | EVAL a = 1 - | EVAL x = a + b - | EVAL y = b + c - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var evalY = as(limit.child(), Eval.class); - assertThat(evalY.fields(), hasSize(1)); - assertThat(evalY.fields().get(0).name(), is("y")); - - var evalX = as(evalY.child(), Eval.class); - assertThat(evalX.fields(), hasSize(1)); - assertThat(evalX.fields().get(0).name(), is("x")); - - var evalABC = as(evalX.child(), Eval.class); - assertThat(Expressions.names(evalABC.fields()), is(List.of("a", "b", "c"))); - for (var field : evalABC.fields()) { - var alias = as(field, Alias.class); - var literal = as(alias.child(), Literal.class); - if (alias.name().equals("a") == false) { - assertThat(literal.dataType(), is(DataType.NULL)); - assertThat(literal.value(), is(nullValue())); - } - } - - var relation = as(evalABC.child(), EsRelation.class); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Eval[[TOLONG(does_not_exist_field{r}#18) AS x#5]] - * \_Eval[[null[NULL] AS does_not_exist_field#18]] - * \_EsRelation[test][_meta_field{f}#13, emp_no{f}#7, first_name{f}#8, ge..] - */ - public void testCasting() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | EVAL x = does_not_exist_field::LONG - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var outerEval = as(limit.child(), Eval.class); - assertThat(outerEval.fields(), hasSize(1)); - var aliasX = as(outerEval.fields().getFirst(), Alias.class); - assertThat(aliasX.name(), is("x")); - assertThat(Expressions.name(aliasX.child()), is("does_not_exist_field::LONG")); - - var innerEval = as(outerEval.child(), Eval.class); - assertThat(innerEval.fields(), hasSize(1)); - var aliasField = as(innerEval.fields().getFirst(), Alias.class); - assertThat(aliasField.name(), is("does_not_exist_field")); - var literal = as(aliasField.child(), Literal.class); - assertThat(literal.dataType(), is(DataType.NULL)); - - var relation = as(innerEval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Eval[[TOLONG(does_not_exist_field{r}#17) AS does_not_exist_field::LONG#4]] - * \_Eval[[null[NULL] AS does_not_exist_field#17]] - * \_EsRelation[test][_meta_field{f}#12, emp_no{f}#6, first_name{f}#7, ge..] - */ - public void testCastingNoAliasing() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | EVAL does_not_exist_field::LONG - """)); - - assertThat(Expressions.names(plan.output()), hasItems("does_not_exist_field", "does_not_exist_field::LONG")); - } - /* * Limit[1000[INTEGER],false,false] * \_Eval[[42[INTEGER] AS does_not_exist_field#7]] @@ -904,429 +314,68 @@ public void testFailStatsThenKeep() { } public void testFailStatsThenEval() { - var query = """ - FROM test - | STATS cnt = COUNT(*) - | EVAL x = does_not_exist_field + cnt - """; - var failure = "line 3:12: Unknown column [does_not_exist_field]"; - verificationFailure(setUnmappedNullify(query), failure); - verificationFailure(setUnmappedLoad(query), failure); - } - - public void testFailStatsThenEvalExistingField() { - var query = """ - FROM test - | STATS cnt = COUNT(*) - | EVAL x = emp_no - """; - var failure = "line 3:12: Unknown column [emp_no]"; - verificationFailure(setUnmappedNullify(query), failure); - verificationFailure(setUnmappedLoad(query), failure); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Aggregate[[],[COUNT(does_not_exist_field{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt#5]] - * \_Eval[[null[NULL] AS does_not_exist_field#18]] - * \_EsRelation[test][_meta_field{f}#13, emp_no{f}#7, first_name{f}#8, ge..] - */ - public void testStatsAgg() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | STATS cnt = COUNT(does_not_exist_field) - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var agg = as(limit.child(), Aggregate.class); - assertThat(agg.groupings(), hasSize(0)); - assertThat(agg.aggregates(), hasSize(1)); - var alias = as(agg.aggregates().getFirst(), Alias.class); - assertThat(alias.name(), is("cnt")); - assertThat(Expressions.name(alias.child()), is("COUNT(does_not_exist_field)")); - - var eval = as(agg.child(), Eval.class); - assertThat(eval.fields(), hasSize(1)); - var aliasField = as(eval.fields().getFirst(), Alias.class); - assertThat(aliasField.name(), is("does_not_exist_field")); - var literal = as(aliasField.child(), Literal.class); - assertThat(literal.dataType(), is(DataType.NULL)); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Aggregate[[does_not_exist_field{r}#16],[does_not_exist_field{r}#16]] - * \_Eval[[null[NULL] AS does_not_exist_field#16]] - * \_EsRelation[test][_meta_field{f}#11, emp_no{f}#5, first_name{f}#6, ge..] - */ - public void testStatsGroup() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | STATS BY does_not_exist_field - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var agg = as(limit.child(), Aggregate.class); - assertThat(agg.groupings(), hasSize(1)); - assertThat(Expressions.name(agg.groupings().getFirst()), is("does_not_exist_field")); - - var eval = as(agg.child(), Eval.class); - assertThat(eval.fields(), hasSize(1)); - var aliasField = as(eval.fields().getFirst(), Alias.class); - assertThat(aliasField.name(), is("does_not_exist_field")); - var literal = as(aliasField.child(), Literal.class); - assertThat(literal.dataType(), is(DataType.NULL)); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Aggregate[[does_not_exist2{r}#19],[SUM(does_not_exist1{r}#20,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s - * #6, does_not_exist2{r}#19]] - * \_Eval[[null[NULL] AS does_not_exist2#19, null[NULL] AS does_not_exist1#20]] - * \_EsRelation[test][_meta_field{f}#14, emp_no{f}#8, first_name{f}#9, ge..] - */ - public void testStatsAggAndGroup() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | STATS s = SUM(does_not_exist1) BY does_not_exist2 - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var agg = as(limit.child(), Aggregate.class); - assertThat(agg.groupings(), hasSize(1)); - assertThat(Expressions.name(agg.groupings().getFirst()), is("does_not_exist2")); - assertThat(agg.aggregates(), hasSize(2)); // includes grouping key - var alias = as(agg.aggregates().getFirst(), Alias.class); - assertThat(alias.name(), is("s")); - assertThat(Expressions.name(alias.child()), is("SUM(does_not_exist1)")); - - var eval = as(agg.child(), Eval.class); - assertThat(eval.fields(), hasSize(2)); - var alias2 = as(eval.fields().getFirst(), Alias.class); - assertThat(alias2.name(), is("does_not_exist2")); - assertThat(as(alias2.child(), Literal.class).dataType(), is(DataType.NULL)); - var alias1 = as(eval.fields().getLast(), Alias.class); - assertThat(alias1.name(), is("does_not_exist1")); - assertThat(as(alias1.child(), Literal.class).dataType(), is(DataType.NULL)); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Aggregate[[does_not_exist2{r}#24 AS d2#5, emp_no{f}#13],[SUM(does_not_exist1{r}#25,true[BOOLEAN],PT0S[TIME_DURATION], - * compensated[KEYWORD]) + d2{r}#5 AS s#10, d2{r}#5, emp_no{f}#13]] - * \_Eval[[null[NULL] AS does_not_exist2#24, null[NULL] AS does_not_exist1#25, null[NULL] AS d2#26]] - * \_EsRelation[test][_meta_field{f}#19, emp_no{f}#13, first_name{f}#14, ..] - */ - public void testStatsAggAndAliasedGroup() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | STATS s = SUM(does_not_exist1) + d2 BY d2 = does_not_exist2, emp_no - """)); - - assertThat(Expressions.names(plan.output()), is(List.of("s", "d2", "emp_no"))); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var agg = as(limit.child(), Aggregate.class); - assertThat(agg.groupings(), hasSize(2)); - var groupAlias = as(agg.groupings().getFirst(), Alias.class); - assertThat(groupAlias.name(), is("d2")); - assertThat(Expressions.name(groupAlias.child()), is("does_not_exist2")); - assertThat(Expressions.name(agg.groupings().get(1)), is("emp_no")); - - assertThat(agg.aggregates(), hasSize(3)); // includes grouping keys - var alias = as(agg.aggregates().getFirst(), Alias.class); - assertThat(alias.name(), is("s")); - assertThat(Expressions.name(alias.child()), is("SUM(does_not_exist1) + d2")); - - var eval = as(agg.child(), Eval.class); - assertThat(eval.fields(), hasSize(3)); - var alias2 = as(eval.fields().get(0), Alias.class); - assertThat(alias2.name(), is("does_not_exist2")); - assertThat(as(alias2.child(), Literal.class).dataType(), is(DataType.NULL)); - var alias1 = as(eval.fields().get(1), Alias.class); - assertThat(alias1.name(), is("does_not_exist1")); - assertThat(as(alias1.child(), Literal.class).dataType(), is(DataType.NULL)); - var alias0 = as(eval.fields().get(2), Alias.class); - assertThat(alias0.name(), is("d2")); - assertThat(as(alias0.child(), Literal.class).dataType(), is(DataType.NULL)); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Aggregate[[does_not_exist2{r}#29 + does_not_exist3{r}#30 AS s0#6, emp_no{f}#18 AS s1#9],[SUM(does_not_exist1{r}#31,true[B - * OOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + s0{r}#6 + s1{r}#9 AS sum#14, s0{r}#6, s1{r}#9]] - * \_Eval[[null[NULL] AS does_not_exist2#29, null[NULL] AS does_not_exist3#30, null[NULL] AS does_not_exist1#31, - * null[NULL] AS s0#32]] - * \_EsRelation[test][_meta_field{f}#24, emp_no{f}#18, first_name{f}#19, ..] - */ - public void testStatsAggAndAliasedGroupWithExpression() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | STATS sum = SUM(does_not_exist1) + s0 + s1 BY s0 = does_not_exist2 + does_not_exist3, s1 = emp_no - """)); - - assertThat(Expressions.names(plan.output()), is(List.of("sum", "s0", "s1"))); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var agg = as(limit.child(), Aggregate.class); - assertThat(agg.groupings(), hasSize(2)); - assertThat(Expressions.names(agg.groupings()), is(List.of("s0", "s1"))); - - assertThat(agg.aggregates(), hasSize(3)); // includes grouping keys - var alias = as(agg.aggregates().getFirst(), Alias.class); - assertThat(alias.name(), is("sum")); - assertThat(Expressions.name(alias.child()), is("SUM(does_not_exist1) + s0 + s1")); - - var eval = as(agg.child(), Eval.class); - assertThat(eval.fields(), hasSize(4)); - assertThat(Expressions.names(eval.fields()), is(List.of("does_not_exist2", "does_not_exist3", "does_not_exist1", "s0"))); - eval.fields().forEach(a -> assertThat(as(as(a, Alias.class).child(), Literal.class).dataType(), is(DataType.NULL))); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Aggregate[[does_not_exist2{r}#22, emp_no{f}#11],[SUM(does_not_exist1{r}#23,true[BOOLEAN],PT0S[TIME_DURATION], - * compensated[KEYWORD]) AS s#7, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#9, does_not_exist2{r}#22, emp_no{f}#11]] - * \_Eval[[null[NULL] AS does_not_exist2#22, null[NULL] AS does_not_exist1#23]] - * \_EsRelation[test][_meta_field{f}#17, emp_no{f}#11, first_name{f}#12, ..] - */ - public void testStatsMixed() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | STATS s = SUM(does_not_exist1), c = COUNT(*) BY does_not_exist2, emp_no - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var agg = as(limit.child(), Aggregate.class); - assertThat(agg.groupings(), hasSize(2)); - assertThat(Expressions.names(agg.groupings()), is(List.of("does_not_exist2", "emp_no"))); - - assertThat(agg.aggregates(), hasSize(4)); // includes grouping keys - assertThat(Expressions.names(agg.aggregates()), is(List.of("s", "c", "does_not_exist2", "emp_no"))); - - var eval = as(agg.child(), Eval.class); - assertThat(eval.fields(), hasSize(2)); - assertThat(Expressions.names(eval.fields()), is(List.of("does_not_exist2", "does_not_exist1"))); - eval.fields().forEach(a -> assertThat(as(as(a, Alias.class).child(), Literal.class).dataType(), is(DataType.NULL))); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_InlineStats[] - * \_Aggregate[[does_not_exist2{r}#22, emp_no{f}#11],[SUM(does_not_exist1{r}#23,true[BOOLEAN],PT0S[TIME_DURATION],compensated[ - * KEYWORD]) AS s#5, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#7, does_not_exist2{r}#22, emp_no{f}#11]] - * \_Eval[[null[NULL] AS does_not_exist2#22, null[NULL] AS does_not_exist1#23]] - * \_EsRelation[test][_meta_field{f}#17, emp_no{f}#11, first_name{f}#12, ..] - */ - public void testInlineStatsMixed() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | INLINE STATS s = SUM(does_not_exist1), c = COUNT(*) BY does_not_exist2, emp_no - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var inlineStats = as(limit.child(), InlineStats.class); - var agg = as(inlineStats.child(), Aggregate.class); - assertThat(agg.groupings(), hasSize(2)); - assertThat(Expressions.names(agg.groupings()), is(List.of("does_not_exist2", "emp_no"))); - - assertThat(agg.aggregates(), hasSize(4)); // includes grouping keys - assertThat(Expressions.names(agg.aggregates()), is(List.of("s", "c", "does_not_exist2", "emp_no"))); - - var eval = as(agg.child(), Eval.class); - assertThat(eval.fields(), hasSize(2)); - assertThat(Expressions.names(eval.fields()), is(List.of("does_not_exist2", "does_not_exist1"))); - eval.fields().forEach(a -> assertThat(as(as(a, Alias.class).child(), Literal.class).dataType(), is(DataType.NULL))); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Aggregate[[does_not_exist3{r}#24, emp_no{f}#13, does_not_exist2{r}#25],[SUM(does_not_exist1{r}#26,true[BOOLEAN], - * PT0S[TIME_DURATION],compensated[KEYWORD]) + does_not_exist2{r}#25 AS s#9, COUNT(*[KEYWORD],true[BOOLEAN], - * PT0S[TIME_DURATION]) AS c#11, does_not_exist3{r}#24, emp_no{f}#13, does_not_exist2{r}#25]] - * \_Eval[[null[NULL] AS does_not_exist3#24, null[NULL] AS does_not_exist2#25]] - * \_EsRelation[test][_meta_field{f}#19, emp_no{f}#13, first_name{f}#14, ..] - */ - public void testStatsMixedAndExpressions() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | STATS s = SUM(does_not_exist1) + does_not_exist2, c = COUNT(*) BY does_not_exist3, emp_no, does_not_exist2 - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var agg = as(limit.child(), Aggregate.class); - assertThat(agg.groupings(), hasSize(3)); - assertThat(Expressions.names(agg.groupings()), is(List.of("does_not_exist3", "emp_no", "does_not_exist2"))); - - assertThat(agg.aggregates(), hasSize(5)); // includes grouping keys - assertThat(Expressions.names(agg.aggregates()), is(List.of("s", "c", "does_not_exist3", "emp_no", "does_not_exist2"))); - - var eval = as(agg.child(), Eval.class); - assertThat(eval.fields(), hasSize(3)); - assertThat(Expressions.names(eval.fields()), is(List.of("does_not_exist3", "does_not_exist2", "does_not_exist1"))); - eval.fields().forEach(a -> assertThat(as(as(a, Alias.class).child(), Literal.class).dataType(), is(DataType.NULL))); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Filter[TOLONG(does_not_exist{r}#33) > 0[INTEGER]] - * \_Eval[[null[NULL] AS does_not_exist#33]] - * \_EsRelation[test][_meta_field{f}#28, emp_no{f}#22, first_name{f}#23, ..] - */ - public void testWhere() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | WHERE does_not_exist::LONG > 0 - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var filter = as(limit.child(), Filter.class); - assertThat(Expressions.name(filter.condition()), is("does_not_exist::LONG > 0")); - - var eval = as(filter.child(), Eval.class); - assertThat(eval.fields(), hasSize(1)); - var alias = as(eval.fields().getFirst(), Alias.class); - assertThat(alias.name(), is("does_not_exist")); - assertThat(as(alias.child(), Literal.class).dataType(), is(DataType.NULL)); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_Filter[TOLONG(does_not_exist{r}#195) > 0[INTEGER] OR emp_no{f}#184 > 0[INTEGER]] - * \_Eval[[null[NULL] AS does_not_exist#195]] - * \_EsRelation[test][_meta_field{f}#190, emp_no{f}#184, first_name{f}#18..] - */ - public void testWhereConjunction() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | WHERE does_not_exist::LONG > 0 OR emp_no > 0 - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var filter = as(limit.child(), Filter.class); - assertThat(Expressions.name(filter.condition()), is("does_not_exist::LONG > 0 OR emp_no > 0")); - - var eval = as(filter.child(), Eval.class); - assertThat(eval.fields(), hasSize(1)); - var alias = as(eval.fields().getFirst(), Alias.class); - assertThat(alias.name(), is("does_not_exist")); - assertThat(as(alias.child(), Literal.class).dataType(), is(DataType.NULL)); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); + var query = """ + FROM test + | STATS cnt = COUNT(*) + | EVAL x = does_not_exist_field + cnt + """; + var failure = "line 3:12: Unknown column [does_not_exist_field]"; + verificationFailure(setUnmappedNullify(query), failure); + verificationFailure(setUnmappedLoad(query), failure); } - /* - * Limit[1000[INTEGER],false,false] - * \_Filter[TOLONG(does_not_exist1{r}#491) > 0[INTEGER] OR emp_no{f}#480 > 0[INTEGER] - * AND TOLONG(does_not_exist2{r}#492) < 100[INTEGER]] - * \_Eval[[null[NULL] AS does_not_exist1#491, null[NULL] AS does_not_exist2#492]] - * \_EsRelation[test][_meta_field{f}#486, emp_no{f}#480, first_name{f}#48..] - */ - public void testWhereConjunctionMultipleFields() { - var plan = analyzeStatement(setUnmappedNullify(""" + public void testFailStatsThenEvalExistingField() { + var query = """ FROM test - | WHERE does_not_exist1::LONG > 0 OR emp_no > 0 AND does_not_exist2::LONG < 100 - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - var filter = as(limit.child(), Filter.class); - assertThat(Expressions.name(filter.condition()), is("does_not_exist1::LONG > 0 OR emp_no > 0 AND does_not_exist2::LONG < 100")); - - var eval = as(filter.child(), Eval.class); - assertThat(eval.fields(), hasSize(2)); - var alias1 = as(eval.fields().get(0), Alias.class); - assertThat(alias1.name(), is("does_not_exist1")); - assertThat(as(alias1.child(), Literal.class).dataType(), is(DataType.NULL)); - var alias2 = as(eval.fields().get(1), Alias.class); - assertThat(alias2.name(), is("does_not_exist2")); - assertThat(as(alias2.child(), Literal.class).dataType(), is(DataType.NULL)); - - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); + | STATS cnt = COUNT(*) + | EVAL x = emp_no + """; + var failure = "line 3:12: Unknown column [emp_no]"; + verificationFailure(setUnmappedNullify(query), failure); + verificationFailure(setUnmappedLoad(query), failure); } /* * Limit[1000[INTEGER],false,false] - * \_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]), - * TOLONG(does_not_exist1{r}#94) > 0[INTEGER]] AS c#81]] - * \_Eval[[null[NULL] AS does_not_exist1#94]] - * \_EsRelation[test][_meta_field{f}#89, emp_no{f}#83, first_name{f}#84, ..] + * \_Aggregate[[does_not_exist2{r}#24 AS d2#5, emp_no{f}#13],[SUM(does_not_exist1{r}#25,true[BOOLEAN],PT0S[TIME_DURATION], + * compensated[KEYWORD]) + d2{r}#5 AS s#10, d2{r}#5, emp_no{f}#13]] + * \_Eval[[null[NULL] AS does_not_exist2#24, null[NULL] AS does_not_exist1#25, null[NULL] AS d2#26]] + * \_EsRelation[test][_meta_field{f}#19, emp_no{f}#13, first_name{f}#14, ..] */ - public void testAggsFiltering() { + public void testStatsAggAndAliasedGroup() { var plan = analyzeStatement(setUnmappedNullify(""" FROM test - | STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 + | STATS s = SUM(does_not_exist1) + d2 BY d2 = does_not_exist2, emp_no """)); + assertThat(Expressions.names(plan.output()), is(List.of("s", "d2", "emp_no"))); + var limit = as(plan, Limit.class); assertThat(limit.limit().fold(FoldContext.small()), is(1000)); var agg = as(limit.child(), Aggregate.class); - assertThat(agg.groupings(), hasSize(0)); - assertThat(agg.aggregates(), hasSize(1)); + assertThat(agg.groupings(), hasSize(2)); + var groupAlias = as(agg.groupings().getFirst(), Alias.class); + assertThat(groupAlias.name(), is("d2")); + assertThat(Expressions.name(groupAlias.child()), is("does_not_exist2")); + assertThat(Expressions.name(agg.groupings().get(1)), is("emp_no")); + + assertThat(agg.aggregates(), hasSize(3)); // includes grouping keys var alias = as(agg.aggregates().getFirst(), Alias.class); - assertThat(alias.name(), is("c")); - var filteredExpr = as(alias.child(), FilteredExpression.class); - var delegate = as(filteredExpr.delegate(), Count.class); - var greaterThan = as(filteredExpr.filter(), GreaterThan.class); - var tolong = as(greaterThan.left(), ToLong.class); - assertThat(Expressions.name(tolong.field()), is("does_not_exist1")); + assertThat(alias.name(), is("s")); + assertThat(Expressions.name(alias.child()), is("SUM(does_not_exist1) + d2")); var eval = as(agg.child(), Eval.class); - assertThat(eval.fields(), hasSize(1)); - var alias1 = as(eval.fields().getFirst(), Alias.class); + assertThat(eval.fields(), hasSize(3)); + var alias2 = as(eval.fields().get(0), Alias.class); + assertThat(alias2.name(), is("does_not_exist2")); + assertThat(as(alias2.child(), Literal.class).dataType(), is(DataType.NULL)); + var alias1 = as(eval.fields().get(1), Alias.class); assertThat(alias1.name(), is("does_not_exist1")); assertThat(as(alias1.child(), Literal.class).dataType(), is(DataType.NULL)); + var alias0 = as(eval.fields().get(2), Alias.class); + assertThat(alias0.name(), is("d2")); + assertThat(as(alias0.child(), Literal.class).dataType(), is(DataType.NULL)); var relation = as(eval.child(), EsRelation.class); assertThat(relation.indexPattern(), is("test")); @@ -1334,109 +383,68 @@ public void testAggsFiltering() { /* * Limit[1000[INTEGER],false,false] - * \_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]), - * TOLONG(does_not_exist1{r}#620) > 0[INTEGER] OR emp_no{f}#609 > 0[INTEGER] - * OR TOLONG(does_not_exist2{r}#621) < 100[INTEGER]] AS c1#602, - * FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{r}#622)] AS c2#607]] - * \_Eval[[null[NULL] AS does_not_exist1#620, null[NULL] AS does_not_exist2#621, null[NULL] AS does_not_exist3#622]] - * \_EsRelation[test][_meta_field{f}#615, emp_no{f}#609, first_name{f}#61..] + * \_Aggregate[[does_not_exist2{r}#29 + does_not_exist3{r}#30 AS s0#6, emp_no{f}#18 AS s1#9],[SUM(does_not_exist1{r}#31,true[B + * OOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + s0{r}#6 + s1{r}#9 AS sum#14, s0{r}#6, s1{r}#9]] + * \_Eval[[null[NULL] AS does_not_exist2#29, null[NULL] AS does_not_exist3#30, null[NULL] AS does_not_exist1#31, + * null[NULL] AS s0#32]] + * \_EsRelation[test][_meta_field{f}#24, emp_no{f}#18, first_name{f}#19, ..] */ - public void testAggsFilteringMultipleFields() { + public void testStatsAggAndAliasedGroupWithExpression() { var plan = analyzeStatement(setUnmappedNullify(""" FROM test - | STATS c1 = COUNT(*) WHERE does_not_exist1::LONG > 0 OR emp_no > 0 OR does_not_exist2::LONG < 100, - c2 = COUNT(*) WHERE does_not_exist3 IS NULL + | STATS sum = SUM(does_not_exist1) + s0 + s1 BY s0 = does_not_exist2 + does_not_exist3, s1 = emp_no """)); + assertThat(Expressions.names(plan.output()), is(List.of("sum", "s0", "s1"))); + var limit = as(plan, Limit.class); assertThat(limit.limit().fold(FoldContext.small()), is(1000)); var agg = as(limit.child(), Aggregate.class); - assertThat(agg.groupings(), hasSize(0)); - assertThat(agg.aggregates(), hasSize(2)); - - var alias1 = as(agg.aggregates().getFirst(), Alias.class); - assertThat(alias1.name(), is("c1")); - assertThat( - Expressions.name(alias1.child()), - is("c1 = COUNT(*) WHERE does_not_exist1::LONG > 0 OR emp_no > 0 OR does_not_exist2::LONG < 100") - ); + assertThat(agg.groupings(), hasSize(2)); + assertThat(Expressions.names(agg.groupings()), is(List.of("s0", "s1"))); - var alias2 = as(agg.aggregates().get(1), Alias.class); - assertThat(alias2.name(), is("c2")); - assertThat(Expressions.name(alias2.child()), is("c2 = COUNT(*) WHERE does_not_exist3 IS NULL")); + assertThat(agg.aggregates(), hasSize(3)); // includes grouping keys + var alias = as(agg.aggregates().getFirst(), Alias.class); + assertThat(alias.name(), is("sum")); + assertThat(Expressions.name(alias.child()), is("SUM(does_not_exist1) + s0 + s1")); var eval = as(agg.child(), Eval.class); - assertThat(eval.fields(), hasSize(3)); - var aliasDne1 = as(eval.fields().get(0), Alias.class); - assertThat(aliasDne1.name(), is("does_not_exist1")); - assertThat(as(aliasDne1.child(), Literal.class).dataType(), is(DataType.NULL)); - var aliasDne2 = as(eval.fields().get(1), Alias.class); - assertThat(aliasDne2.name(), is("does_not_exist2")); - assertThat(as(aliasDne2.child(), Literal.class).dataType(), is(DataType.NULL)); - var aliasDne3 = as(eval.fields().get(2), Alias.class); - assertThat(aliasDne3.name(), is("does_not_exist3")); - assertThat(as(aliasDne3.child(), Literal.class).dataType(), is(DataType.NULL)); + assertThat(eval.fields(), hasSize(4)); + assertThat(Expressions.names(eval.fields()), is(List.of("does_not_exist2", "does_not_exist3", "does_not_exist1", "s0"))); + eval.fields().forEach(a -> assertThat(as(as(a, Alias.class).child(), Literal.class).dataType(), is(DataType.NULL))); var relation = as(eval.child(), EsRelation.class); assertThat(relation.indexPattern(), is("test")); } /* - * Limit[1000[INTEGER],false,false] - * \_OrderBy[[Order[does_not_exist{r}#16,ASC,LAST]]] - * \_Eval[[null[NULL] AS does_not_exist#16]] - * \_EsRelation[test][_meta_field{f}#11, emp_no{f}#5, first_name{f}#6, ge..] - */ - public void testSort() { + * Limit[1000[INTEGER],false,false] + * \_Aggregate[[does_not_exist2{r}#22, emp_no{f}#11],[SUM(does_not_exist1{r}#23,true[BOOLEAN],PT0S[TIME_DURATION], + * compensated[KEYWORD]) AS s#7, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#9, does_not_exist2{r}#22, emp_no{f}#11]] + * \_Eval[[null[NULL] AS does_not_exist2#22, null[NULL] AS does_not_exist1#23]] + * \_EsRelation[test][_meta_field{f}#17, emp_no{f}#11, first_name{f}#12, ..] + */ + public void testStatsMixed() { var plan = analyzeStatement(setUnmappedNullify(""" FROM test - | SORT does_not_exist ASC + | STATS s = SUM(does_not_exist1), c = COUNT(*) BY does_not_exist2, emp_no """)); - // Top implicit limit 1000 var limit = as(plan, Limit.class); assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - // OrderBy over the Eval-produced alias - var orderBy = as(limit.child(), OrderBy.class); - - // Eval introduces does_not_exist as NULL - var eval = as(orderBy.child(), Eval.class); - assertThat(eval.fields(), hasSize(1)); - var alias = as(eval.fields().getFirst(), Alias.class); - assertThat(alias.name(), is("does_not_exist")); - assertThat(as(alias.child(), Literal.class).dataType(), is(DataType.NULL)); - - // Underlying relation - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_OrderBy[[Order[TOLONG(does_not_exist{r}#485) + 1[INTEGER],ASC,LAST]]] - * \_Eval[[null[NULL] AS does_not_exist#485]] - * \_EsRelation[test][_meta_field{f}#480, emp_no{f}#474, first_name{f}#47..] - */ - public void testSortExpression() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | SORT does_not_exist::LONG + 1 - """)); - - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); + var agg = as(limit.child(), Aggregate.class); + assertThat(agg.groupings(), hasSize(2)); + assertThat(Expressions.names(agg.groupings()), is(List.of("does_not_exist2", "emp_no"))); - var orderBy = as(limit.child(), OrderBy.class); - assertThat(orderBy.order(), hasSize(1)); - assertThat(Expressions.name(orderBy.order().getFirst().child()), is("does_not_exist::LONG + 1")); + assertThat(agg.aggregates(), hasSize(4)); // includes grouping keys + assertThat(Expressions.names(agg.aggregates()), is(List.of("s", "c", "does_not_exist2", "emp_no"))); - var eval = as(orderBy.child(), Eval.class); - assertThat(eval.fields(), hasSize(1)); - var alias = as(eval.fields().getFirst(), Alias.class); - assertThat(alias.name(), is("does_not_exist")); - assertThat(as(alias.child(), Literal.class).dataType(), is(DataType.NULL)); + var eval = as(agg.child(), Eval.class); + assertThat(eval.fields(), hasSize(2)); + assertThat(Expressions.names(eval.fields()), is(List.of("does_not_exist2", "does_not_exist1"))); + eval.fields().forEach(a -> assertThat(as(as(a, Alias.class).child(), Literal.class).dataType(), is(DataType.NULL))); var relation = as(eval.child(), EsRelation.class); assertThat(relation.indexPattern(), is("test")); @@ -1444,34 +452,33 @@ public void testSortExpression() { /* * Limit[1000[INTEGER],false,false] - * \_OrderBy[[Order[TOLONG(does_not_exist{r}#370) + 1[INTEGER],ASC,LAST], Order[does_not_exist2{r}#371,DESC,FIRST], - * Order[emp_no{f}#359,ASC,LAST]]] - * \_Eval[[null[NULL] AS does_not_exist1#370, null[NULL] AS does_not_exist2#371]] - * \_EsRelation[test][_meta_field{f}#365, emp_no{f}#359, first_name{f}#36..] + * \_InlineStats[] + * \_Aggregate[[does_not_exist2{r}#22, emp_no{f}#11],[SUM(does_not_exist1{r}#23,true[BOOLEAN],PT0S[TIME_DURATION],compensated[ + * KEYWORD]) AS s#5, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#7, does_not_exist2{r}#22, emp_no{f}#11]] + * \_Eval[[null[NULL] AS does_not_exist2#22, null[NULL] AS does_not_exist1#23]] + * \_EsRelation[test][_meta_field{f}#17, emp_no{f}#11, first_name{f}#12, ..] */ - public void testSortExpressionMultipleFields() { + public void testInlineStatsMixed() { var plan = analyzeStatement(setUnmappedNullify(""" FROM test - | SORT does_not_exist1::LONG + 1, does_not_exist2 DESC, emp_no ASC + | INLINE STATS s = SUM(does_not_exist1), c = COUNT(*) BY does_not_exist2, emp_no """)); var limit = as(plan, Limit.class); assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - var orderBy = as(limit.child(), OrderBy.class); - assertThat(orderBy.order(), hasSize(3)); - assertThat(Expressions.name(orderBy.order().get(0).child()), is("does_not_exist1::LONG + 1")); - assertThat(Expressions.name(orderBy.order().get(1).child()), is("does_not_exist2")); - assertThat(Expressions.name(orderBy.order().get(2).child()), is("emp_no")); + var inlineStats = as(limit.child(), InlineStats.class); + var agg = as(inlineStats.child(), Aggregate.class); + assertThat(agg.groupings(), hasSize(2)); + assertThat(Expressions.names(agg.groupings()), is(List.of("does_not_exist2", "emp_no"))); + + assertThat(agg.aggregates(), hasSize(4)); // includes grouping keys + assertThat(Expressions.names(agg.aggregates()), is(List.of("s", "c", "does_not_exist2", "emp_no"))); - var eval = as(orderBy.child(), Eval.class); + var eval = as(agg.child(), Eval.class); assertThat(eval.fields(), hasSize(2)); - var alias1 = as(eval.fields().get(0), Alias.class); - assertThat(alias1.name(), is("does_not_exist1")); - assertThat(as(alias1.child(), Literal.class).dataType(), is(DataType.NULL)); - var alias2 = as(eval.fields().get(1), Alias.class); - assertThat(alias2.name(), is("does_not_exist2")); - assertThat(as(alias2.child(), Literal.class).dataType(), is(DataType.NULL)); + assertThat(Expressions.names(eval.fields()), is(List.of("does_not_exist2", "does_not_exist1"))); + eval.fields().forEach(a -> assertThat(as(as(a, Alias.class).child(), Literal.class).dataType(), is(DataType.NULL))); var relation = as(eval.child(), EsRelation.class); assertThat(relation.indexPattern(), is("test")); @@ -1479,27 +486,32 @@ public void testSortExpressionMultipleFields() { /* * Limit[1000[INTEGER],false,false] - * \_MvExpand[does_not_exist{r}#17,does_not_exist{r}#20] - * \_Eval[[null[NULL] AS does_not_exist#17]] - * \_EsRelation[test][_meta_field{f}#12, emp_no{f}#6, first_name{f}#7, ge..] + * \_Aggregate[[does_not_exist3{r}#24, emp_no{f}#13, does_not_exist2{r}#25],[SUM(does_not_exist1{r}#26,true[BOOLEAN], + * PT0S[TIME_DURATION],compensated[KEYWORD]) + does_not_exist2{r}#25 AS s#9, COUNT(*[KEYWORD],true[BOOLEAN], + * PT0S[TIME_DURATION]) AS c#11, does_not_exist3{r}#24, emp_no{f}#13, does_not_exist2{r}#25]] + * \_Eval[[null[NULL] AS does_not_exist3#24, null[NULL] AS does_not_exist2#25]] + * \_EsRelation[test][_meta_field{f}#19, emp_no{f}#13, first_name{f}#14, ..] */ - public void testMvExpand() { + public void testStatsMixedAndExpressions() { var plan = analyzeStatement(setUnmappedNullify(""" FROM test - | MV_EXPAND does_not_exist + | STATS s = SUM(does_not_exist1) + does_not_exist2, c = COUNT(*) BY does_not_exist3, emp_no, does_not_exist2 """)); var limit = as(plan, Limit.class); assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - var mvExpand = as(limit.child(), MvExpand.class); - assertThat(Expressions.name(mvExpand.expanded()), is("does_not_exist")); + var agg = as(limit.child(), Aggregate.class); + assertThat(agg.groupings(), hasSize(3)); + assertThat(Expressions.names(agg.groupings()), is(List.of("does_not_exist3", "emp_no", "does_not_exist2"))); - var eval = as(mvExpand.child(), Eval.class); - assertThat(eval.fields(), hasSize(1)); - var alias = as(eval.fields().getFirst(), Alias.class); - assertThat(alias.name(), is("does_not_exist")); - assertThat(as(alias.child(), Literal.class).dataType(), is(DataType.NULL)); + assertThat(agg.aggregates(), hasSize(5)); // includes grouping keys + assertThat(Expressions.names(agg.aggregates()), is(List.of("s", "c", "does_not_exist3", "emp_no", "does_not_exist2"))); + + var eval = as(agg.child(), Eval.class); + assertThat(eval.fields(), hasSize(3)); + assertThat(Expressions.names(eval.fields()), is(List.of("does_not_exist3", "does_not_exist2", "does_not_exist1"))); + eval.fields().forEach(a -> assertThat(as(as(a, Alias.class).child(), Literal.class).dataType(), is(DataType.NULL))); var relation = as(eval.child(), EsRelation.class); assertThat(relation.indexPattern(), is("test")); @@ -3028,40 +2040,6 @@ public void testForkBranchesWithDifferentSchemas() { assertThat(rel.indexPattern(), is("test")); } - /* - * Limit[1000[INTEGER],false,false] - * \_OrderBy[[Order[does_not_exist2{r}#46,ASC,LAST]]] - * \_Fork[[c{r}#45, does_not_exist2{r}#46, _fork{r}#47, d{r}#48]] - * |_Limit[1000[INTEGER],false,false] - * | \_Project[[c{r}#6, does_not_exist2{r}#39, _fork{r}#7, d{r}#42]] - * | \_Eval[[null[DOUBLE] AS d#42]] - * | \_Eval[[fork1[KEYWORD] AS _fork#7]] - * | \_Aggregate[[does_not_exist2{r}#39],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#6, does_not_exist2{r}#39]] - * | \_Filter[ISNULL(does_not_exist1{r}#35)] - * | \_Eval[[null[NULL] AS does_not_exist1#35, null[NULL] AS does_not_exist2#39]] - * | \_EsRelation[test][_meta_field{f}#19, emp_no{f}#13, first_name{f}#14, ..] - * \_Limit[1000[INTEGER],false,false] - * \_Project[[c{r}#43, does_not_exist2{r}#44, _fork{r}#7, d{r}#10]] - * \_Eval[[null[LONG] AS c#43, null[NULL] AS does_not_exist2#44]] - * \_Eval[[fork2[KEYWORD] AS _fork#7]] - * \_Aggregate[[],[AVG(salary{f}#29,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS d#10]] - * \_Filter[ISNULL(does_not_exist1{r}#37)] - * \_Eval[[null[NULL] AS does_not_exist1#37]] - * \_EsRelation[test][_meta_field{f}#30, emp_no{f}#24, first_name{f}#25, ..] - */ - public void testForkBranchesAfterStats1stBranch() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | WHERE does_not_exist1 IS NULL - | FORK (STATS c = COUNT(*) BY does_not_exist2) - (STATS d = AVG(salary)) - | SORT does_not_exist2 - """)); - - // TODO: golden testing - assertThat(Expressions.names(plan.output()), is(List.of("c", "does_not_exist2", "_fork", "d"))); - } - /* * Limit[1000[INTEGER],false,false] * \_OrderBy[[Order[does_not_exist2{r}#48,ASC,LAST]]] @@ -3112,100 +2090,6 @@ public void testFailAfterForkOfStats() { verificationFailure(setUnmappedLoad(query), failure); } - /* - * Limit[1000[INTEGER],false,false] - * \_InlineStats[] - * \_Aggregate[[does_not_exist2{r}#19],[SUM(does_not_exist1{r}#20,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS c#5, - * does_not_exist2{r}#19]] - * \_Eval[[null[NULL] AS does_not_exist2#19, null[NULL] AS does_not_exist1#20]] - * \_EsRelation[test][_meta_field{f}#14, emp_no{f}#8, first_name{f}#9, ge..] - */ - public void testInlineStats() { - var plan = analyzeStatement(setUnmappedNullify(""" - FROM test - | INLINE STATS c = SUM(does_not_exist1) BY does_not_exist2 - """)); - - // Top implicit limit 1000 - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - // InlineStats wrapping Aggregate - var inlineStats = as(limit.child(), InlineStats.class); - var agg = as(inlineStats.child(), Aggregate.class); - - // Grouping by does_not_exist2 and SUM over does_not_exist1 - assertThat(agg.groupings(), hasSize(1)); - var groupRef = as(agg.groupings().getFirst(), ReferenceAttribute.class); - assertThat(groupRef.name(), is("does_not_exist2")); - - assertThat(agg.aggregates(), hasSize(2)); - var cAlias = as(agg.aggregates().getFirst(), Alias.class); - assertThat(cAlias.name(), is("c")); - as(cAlias.child(), Sum.class); - - // Upstream Eval introduces does_not_exist2 and does_not_exist1 as NULL - var eval = as(agg.child(), Eval.class); - assertThat(eval.fields(), hasSize(2)); - - var dne2Alias = as(eval.fields().get(0), Alias.class); - assertThat(dne2Alias.name(), is("does_not_exist2")); - assertThat(as(dne2Alias.child(), Literal.class).dataType(), is(DataType.NULL)); - - var dne1Alias = as(eval.fields().get(1), Alias.class); - assertThat(dne1Alias.name(), is("does_not_exist1")); - assertThat(as(dne1Alias.child(), Literal.class).dataType(), is(DataType.NULL)); - - // Underlying relation - var relation = as(eval.child(), EsRelation.class); - assertThat(relation.indexPattern(), is("test")); - } - - /* - * Limit[1000[INTEGER],false,false] - * \_LookupJoin[LEFT,[language_code{r}#5],[language_code{f}#19],false,null] - * |_Eval[[TOINTEGER(does_not_exist{r}#21) AS language_code#5]] - * | \_Eval[[null[NULL] AS does_not_exist#21]] - * | \_EsRelation[test][_meta_field{f}#14, emp_no{f}#8, first_name{f}#9, ge..] - * \_EsRelation[languages_lookup][LOOKUP][language_code{f}#19, language_name{f}#20] - */ - public void testLookupJoin() { - String query = """ - FROM test - | EVAL language_code = does_not_exist::INTEGER - | LOOKUP JOIN languages_lookup ON language_code - """; - var plan = analyzeStatement(setUnmappedNullify(query)); - - // Top implicit limit 1000 - var limit = as(plan, Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), is(1000)); - - // LookupJoin over alias `language_code` - var lj = as(limit.child(), LookupJoin.class); - assertThat(lj.config().type(), is(JoinTypes.LEFT)); - - // Left child: EVAL language_code = TOINTEGER(does_not_exist), with upstream NULL alias for does_not_exist - var leftEval = as(lj.left(), Eval.class); - assertThat(leftEval.fields(), hasSize(1)); - var langCodeAlias = as(leftEval.fields().getFirst(), Alias.class); - assertThat(langCodeAlias.name(), is("language_code")); - as(langCodeAlias.child(), ToInteger.class); - - var upstreamEval = as(leftEval.child(), Eval.class); - assertThat(upstreamEval.fields(), hasSize(1)); - var dneAlias = as(upstreamEval.fields().getFirst(), Alias.class); - assertThat(dneAlias.name(), is("does_not_exist")); - assertThat(as(dneAlias.child(), Literal.class).dataType(), is(DataType.NULL)); - - var leftRel = as(upstreamEval.child(), EsRelation.class); - assertThat(leftRel.indexPattern(), is("test")); - - // Right lookup table - var rightRel = as(lj.right(), EsRelation.class); - assertThat(rightRel.indexPattern(), is("languages_lookup")); - } - public void testFailLookupJoinWithoutCast() { String query = """ FROM test From 4f355ac273f96df7cf7145c843c20ac26625df4e Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 4 Mar 2026 17:24:05 +0200 Subject: [PATCH 092/137] Add TS vs non-TS unmapped field tests Add tests covering cases where time-series aggregation behaves differently from non-TS when handling unmapped fields: unmapped-load.csv-spec: - statsImplicitLastOverTimeUnmappedTsIndex: max(max_over_time(event_log)) on unmapped metric with load - statsByUnmappedFieldTsIndex: STATS BY unmapped event_log on TS index (uses COUNT(events_received) since TS rejects COUNT(*)) - explicitLastOverTimeUnmappedTsIndex: explicit max_over_time on unmapped unmapped-nullify.csv-spec: - unmappedFieldNullifiedTsIndex: unmapped event_log nullified on TS index - rateOnUnmappedTsIndex: RATE(nonexistent_counter) with nullify - explicitLastOverTimeUnmappedNullifyTsIndex: max_over_time on nullified unmapped field Add k8s_unmapped index (mapping omits event_log, uses k8s.csv) to support these TS unmapped tests. Made-with: Cursor --- .../xpack/esql/CsvTestsDataLoader.java | 1 + .../index/mappings/mapping-k8s-unmapped.json | 96 ++++++++++++ .../src/main/resources/unmapped-load.csv-spec | 140 ++++++++++++++++++ .../main/resources/unmapped-nullify.csv-spec | 55 +++++++ 4 files changed, 292 insertions(+) create mode 100644 x-pack/plugin/esql/qa/testFixtures/src/main/resources/index/mappings/mapping-k8s-unmapped.json diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java index 4c4e0f80bc2ee..0306b1b33dd67 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java @@ -166,6 +166,7 @@ public class CsvTestsDataLoader { new TestDataset("date_nanos"), new TestDataset("date_nanos_union_types"), new TestDataset("k8s", "k8s-mappings.json", "k8s.csv").withSetting("k8s-settings.json"), + new TestDataset("k8s_unmapped", "mapping-k8s-unmapped.json", "k8s.csv").withSetting("k8s-settings.json"), new TestDataset("datenanos-k8s", "k8s-mappings-date_nanos.json", "k8s.csv", "k8s-settings.json"), new TestDataset("k8s-downsampled", "k8s-downsampled-mappings.json", "k8s-downsampled.csv", "k8s-downsampled-settings.json"), new TestDataset("distances"), diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/index/mappings/mapping-k8s-unmapped.json b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/index/mappings/mapping-k8s-unmapped.json new file mode 100644 index 0000000000000..f5fd00ff5d766 --- /dev/null +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/index/mappings/mapping-k8s-unmapped.json @@ -0,0 +1,96 @@ +{ + "dynamic": "false", + "properties": { + "@timestamp": { + "type": "date" + }, + "cluster": { + "type": "keyword", + "time_series_dimension": true + }, + "pod": { + "type": "keyword", + "time_series_dimension": true + }, + "client": { + "properties": { + "ip": { + "type": "ip" + } + } + }, + "region": { + "type": "keyword", + "time_series_dimension": true + }, + "event": { + "type": "keyword" + }, + "events_received": { + "type": "long" + }, + "event_city": { + "type": "geo_point" + }, + "event_city_boundary": { + "type": "geo_shape" + }, + "event_shape": { + "type": "shape" + }, + "event_location": { + "type": "point" + }, + "network": { + "properties": { + "bytes_in": { + "type": "long" + }, + "total_bytes_in": { + "type": "long", + "time_series_metric": "counter", + "meta": { "unit": "bytes" } + }, + "total_bytes_out": { + "type": "long", + "time_series_metric": "counter", + "meta": { "unit": "bytes" } + }, + "cost": { + "type": "double" + }, + "total_cost": { + "type": "double", + "time_series_metric": "counter", + "meta": { "unit": "usd" } + }, + "eth0": { + "properties": { + "up": { + "type": "boolean" + }, + "tx": { + "type": "integer", + "time_series_metric": "gauge", + "meta": { "unit": "packets" } + }, + "rx": { + "type": "integer", + "time_series_metric": "gauge", + "meta": { "unit": "packets" } + }, + "last_up": { + "type": "date_nanos" + }, + "firmware_version": { + "type": "version" + }, + "currently_connected_clients": { + "type": "integer" + } + } + } + } + } + } +} diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index 8a3b243717ea6..c55ec274d0b4b 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -187,6 +187,146 @@ FROM partial_mapping_sample_data 2024-10-23T12:15:03.360Z | Connected to 10.1.0.3! | Disconnected from 10.1.0.3 ; +statsByUnmappedFieldExistsInSource +required_capability: unmapped_fields +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM partial_mapping_sample_data +| STATS s = SUM(event_duration), c = COUNT(*) BY unmapped_message +| SORT unmapped_message +; + +s:long | c:long | unmapped_message:keyword +1232381 | 1 | 43 +1756466 | 1 | Disconnected from 10.1.0.1 +2764888 | 1 | Disconnected from 10.1.0.2 +3450232 | 1 | Disconnected from 10.1.0.3 +14027353 | 3 | Disconnection error +; + +inlineStatsByUnmappedFieldExistsInSource +required_capability: unmapped_fields +required_capability: optional_fields_v2 +required_capability: inline_stats + +SET unmapped_fields="load"\; +FROM partial_mapping_sample_data +| KEEP @timestamp, event_duration, unmapped_message +| INLINE STATS s = SUM(event_duration), c = COUNT(*) BY unmapped_message +| SORT @timestamp DESC +| LIMIT 4 +; + +@timestamp:datetime | event_duration:long | s:long | c:long | unmapped_message:keyword +2024-10-23T13:55:01.543Z | 1756466 | 1756466 | 1 | Disconnected from 10.1.0.1 +2024-10-23T13:53:55.832Z | 5033754 | 14027353 | 3 | Disconnection error +2024-10-23T13:52:55.015Z | 8268152 | 14027353 | 3 | Disconnection error +2024-10-23T13:51:54.732Z | 725447 | 14027353 | 3 | Disconnection error +; + +unmappedFieldExistsInSourceTsIndex +required_capability: unmapped_fields +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM k8s_unmapped +| EVAL event_log = SUBSTRING(event_log, 1, 10) +| KEEP @timestamp, cluster, event_log +| SORT @timestamp +| LIMIT 5 +; + +@timestamp:date | cluster:keyword | event_log:keyword +2024-05-10T00:00:29.000Z | staging | Lorem ipsu +2024-05-10T00:00:33.000Z | staging | interdum r +2024-05-10T00:00:51.000Z | prod | integer, n +2024-05-10T00:00:57.000Z | prod | tortor fel +2024-05-10T00:01:25.000Z | qa | dapibus co +; + +unmappedFieldNonExistentTsIndex +required_capability: unmapped_fields +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM k8s_unmapped +| KEEP @timestamp, cluster, nonexistent_field +| SORT @timestamp +| LIMIT 5 +; + +@timestamp:date | cluster:keyword | nonexistent_field:keyword +2024-05-10T00:00:29.000Z | staging | null +2024-05-10T00:00:33.000Z | staging | null +2024-05-10T00:00:51.000Z | prod | null +2024-05-10T00:00:57.000Z | prod | null +2024-05-10T00:01:25.000Z | qa | null +; + +statsImplicitLastOverTimeUnmappedTsIndex +required_capability: unmapped_fields +required_capability: optional_fields_v2 +required_capability: ts_command_v0 + +SET unmapped_fields="load"\; +TS k8s_unmapped +| STATS x = max(max_over_time(event_log)) BY time_bucket = bucket(@timestamp, 10minute) +| SORT time_bucket +| LIMIT 5 +; + +x:keyword | time_bucket:datetime +vulputate suscipit fames imperdiet per scelerisque viverra. Odio sem mi molestie luctus dictumst sagittis inceptos, sociis congue aenean vitae himenaeos quam sociosqu, class parturient | 2024-05-10T00:00:00.000Z +vulputate quisque neque aliquam per cras sed mauris cubilia, ornare netus id laoreet bibendum lacus lacinia | 2024-05-10T00:10:00.000Z +volutpat vestibulum elementum auctor | 2024-05-10T00:20:00.000Z +; + +statsByUnmappedFieldTsIndex +required_capability: unmapped_fields +required_capability: optional_fields_v2 +required_capability: ts_command_v0 + +SET unmapped_fields="load"\; +TS k8s_unmapped +| STATS s = SUM(events_received), c = COUNT(events_received) BY event_log +| SORT event_log +| LIMIT 10 +; + +s:long | c:long | event_log:keyword +6 | 1 | Aenean himenaeos urna +3 | 1 | Cubilia lacinia luctus tincidunt convallis ridiculus habitant vel potenti, arcu pellentesque semper sociis ac felis. Vitae sagittis natoque mollis arcu diam lacus sociosqu, lacinia suspendisse quisque tristique cursus phasellus. +2 | 1 | Lorem ipsum dolor sit amet consectetur adipiscing elit nulla ut in +3 | 1 | Lorem ipsum dolor sit amet consectetur adipiscing elit nulla ut in nullam tristique viverra penatibus ac integer +2 | 1 | Nunc +4 | 1 | Nunc tortor maecenas turpis donec est rutrum penatibus, velit quam ante condimentum dictum at nibh, nisl a lobortis lacus ultrices primis, vulputate quis volutpat hac tristique mattis. Hendrerit integer mattis +7 | 1 | Placerat mi litora fringilla tellus pretium aliquet ut ridiculus magnis magna, interdum dictumst lacinia hendrerit +6 | 1 | Scelerisque donec luctus laoreet vulputate phasellus interdum cursus a +4 | 1 | Scelerisque donec luctus laoreet vulputate phasellus interdum cursus a sapien, +5 | 1 | Sed ultricies mus nostra mauris vivamus velit habitant aenean, venenatis nisi parturient faucibus facilisis himenaeos varius, nunc dictumst per metus magna +; + +explicitLastOverTimeUnmappedTsIndex +required_capability: unmapped_fields +required_capability: optional_fields_v2 +required_capability: ts_command_v0 + +SET unmapped_fields="load"\; +TS k8s_unmapped +| STATS x = max(max_over_time(event_log)) BY cluster, time_bucket = bucket(@timestamp, 10minute) +| SORT cluster, time_bucket +| LIMIT 5 +; + +x:keyword | cluster:keyword | time_bucket:datetime +vivamus, sociis erat lectus torquent luctus pharetra, nunc cubilia imperdiet malesuada. Scelerisque donec luctus laoreet vulputate phasellus interdum cursus a sapien, penatibus dictum malesuada nostra suscipit congue aptent sociis, dictumst | prod | 2024-05-10T00:00:00.000Z +vivamus, sociis erat lectus torquent luctus pharetra, nunc cubilia imperdiet malesuada. Scelerisque donec luctus laoreet vulputate phasellus interdum cursus a sapien, penatibus dictum malesuada nostra suscipit | prod | 2024-05-10T00:10:00.000Z +volutpat vestibulum elementum auctor | prod | 2024-05-10T00:20:00.000Z +vulputate quisque neque aliquam per cras sed mauris cubilia, | qa | 2024-05-10T00:00:00.000Z +volutpat hac tristique mattis. Hendrerit integer mattis venenatis nibh ad nascetur posuere et, viverra tincidunt eu sagittis torquent nunc velit, nulla auctor molestie pellentesque lacinia | qa | 2024-05-10T00:10:00.000Z +; + # Kept this test disabled to show the difference from IGNORE_🐔: if everywhere unmapped and not mentioned, a field (message) won't show # up at all. fieldIsUnmappedButSourceIsDisabledSingleIndex-Ignore diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec index a70d9a79e7561..d0caa2045950e 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec @@ -588,3 +588,58 @@ sample_data | 2023-10-23T13:33:34.937Z | Disconnected sample_data | 2023-10-23T12:27:28.948Z | Connected to 10.1.0.2 sample_data | 2023-10-23T12:15:03.360Z | Connected to 10.1.0.3 ; + +unmappedFieldNullifiedTsIndex +required_capability: optional_fields_nullify_tech_preview +required_capability: ts_command_v0 + +SET unmapped_fields="nullify"\; +TS k8s_unmapped +| KEEP @timestamp, cluster, event_log +| SORT @timestamp +| LIMIT 5 +; + +@timestamp:date | cluster:keyword | event_log:null +2024-05-10T00:00:29.000Z | staging | null +2024-05-10T00:00:33.000Z | staging | null +2024-05-10T00:00:51.000Z | prod | null +2024-05-10T00:00:57.000Z | prod | null +2024-05-10T00:01:25.000Z | qa | null +; + +rateOnUnmappedTsIndex +required_capability: optional_fields_nullify_tech_preview +required_capability: ts_command_v0 +required_capability: tbucket +required_capability: fix_agg_on_null_by_replacing_with_eval + +SET unmapped_fields="nullify"\; +TS k8s_unmapped +| STATS r = MAX(RATE(nonexistent_counter)) BY tbucket = tbucket(1 hour) +| SORT tbucket +| LIMIT 3 +; + +r:double | tbucket:datetime +null | 2024-05-10T00:00:00.000Z +; + +explicitLastOverTimeUnmappedNullifyTsIndex +required_capability: optional_fields_nullify_tech_preview +required_capability: ts_command_v0 + +SET unmapped_fields="nullify"\; +TS k8s_unmapped +| STATS x = max(max_over_time(event_log)) BY cluster, time_bucket = bucket(@timestamp, 10minute) +| SORT cluster, time_bucket +| LIMIT 5 +; + +x:null | cluster:keyword | time_bucket:datetime +null | prod | 2024-05-10T00:00:00.000Z +null | prod | 2024-05-10T00:10:00.000Z +null | prod | 2024-05-10T00:20:00.000Z +null | qa | 2024-05-10T00:00:00.000Z +null | qa | 2024-05-10T00:10:00.000Z +; From a07554fc5b0bae611dcb28553417e686ae96c8af Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Thu, 5 Mar 2026 11:05:06 +0000 Subject: [PATCH 093/137] [CI] Auto commit changes from spotless --- .../xpack/esql/analysis/AnalyzerUnmappedTests.java | 8 -------- .../xpack/esql/optimizer/GoldenTestCase.java | 2 +- .../xpack/esql/optimizer/UnmappedGoldenTestCase.java | 12 +++--------- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index ca8efd6f2fd09..eba7a5c2d2fb8 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -21,13 +21,10 @@ import org.elasticsearch.xpack.esql.core.expression.UnresolvedTimestamp; import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.core.type.PotentiallyUnmappedKeywordEsField; -import org.elasticsearch.xpack.esql.expression.function.aggregate.Count; import org.elasticsearch.xpack.esql.expression.function.aggregate.FilteredExpression; import org.elasticsearch.xpack.esql.expression.function.aggregate.Max; -import org.elasticsearch.xpack.esql.expression.function.aggregate.Sum; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ConvertFunction; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDouble; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToInteger; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToLong; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToString; import org.elasticsearch.xpack.esql.expression.predicate.logical.And; @@ -44,14 +41,11 @@ import org.elasticsearch.xpack.esql.plan.logical.Fork; import org.elasticsearch.xpack.esql.plan.logical.InlineStats; import org.elasticsearch.xpack.esql.plan.logical.Limit; -import org.elasticsearch.xpack.esql.plan.logical.MvExpand; import org.elasticsearch.xpack.esql.plan.logical.OrderBy; import org.elasticsearch.xpack.esql.plan.logical.Project; import org.elasticsearch.xpack.esql.plan.logical.Row; import org.elasticsearch.xpack.esql.plan.logical.Subquery; import org.elasticsearch.xpack.esql.plan.logical.UnionAll; -import org.elasticsearch.xpack.esql.plan.logical.join.JoinTypes; -import org.elasticsearch.xpack.esql.plan.logical.join.LookupJoin; import java.util.List; @@ -61,12 +55,10 @@ import static org.elasticsearch.xpack.esql.analysis.AnalyzerTests.withInlinestatsWarning; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; // @TestLogging(value = "org.elasticsearch.xpack.esql:TRACE", reason = "debug") public class AnalyzerUnmappedTests extends ESTestCase { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index cb522973326ef..53f1e020fc672 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -57,11 +57,11 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Optional; import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.BiFunction; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/UnmappedGoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/UnmappedGoldenTestCase.java index d15bad64dfdb5..0b53ce0c14f3f 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/UnmappedGoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/UnmappedGoldenTestCase.java @@ -24,21 +24,15 @@ protected void runTestsNullifyAndLoad(String query, EnumSet stages) { e ); }); - loadException.ifPresent(e -> { - throw new RuntimeException("Load mode failed (but nullify succeeded)", e); - }); + loadException.ifPresent(e -> { throw new RuntimeException("Load mode failed (but nullify succeeded)", e); }); } protected void runTestsNullifyOnly(String query, EnumSet stages) { - tryRunTestsNullifyOnly(query, stages).ifPresent(e -> { - throw new RuntimeException("Nullify mode failed", e); - }); + tryRunTestsNullifyOnly(query, stages).ifPresent(e -> { throw new RuntimeException("Nullify mode failed", e); }); } protected void runTestsLoadOnly(String query, EnumSet stages) { - tryRunTestsLoadOnly(query, stages).ifPresent(e -> { - throw new RuntimeException("Load mode failed", e); - }); + tryRunTestsLoadOnly(query, stages).ifPresent(e -> { throw new RuntimeException("Load mode failed", e); }); } private Optional tryRunTestsNullifyOnly(String query, EnumSet stages) { From 1ab3eed1a806174f8e345a2a927ed903a4e5e84d Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 5 Mar 2026 14:11:28 +0200 Subject: [PATCH 094/137] Fix k8s star tests --- .../main/resources/k8s-timeseries-avg-over-time.csv-spec | 4 ++-- .../resources/k8s-timeseries-count-over-time.csv-spec | 4 ++-- .../main/resources/k8s-timeseries-max-over-time.csv-spec | 8 ++++---- .../main/resources/k8s-timeseries-min-over-time.csv-spec | 8 ++++---- .../main/resources/k8s-timeseries-sum-over-time.csv-spec | 8 ++++---- .../src/main/resources/k8s-timeseries.csv-spec | 4 ++-- .../elasticsearch/xpack/esql/analysis/AnalyzerTests.java | 8 ++++---- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-avg-over-time.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-avg-over-time.csv-spec index 90db4834c55ea..5a360d0b305df 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-avg-over-time.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-avg-over-time.csv-spec @@ -253,7 +253,7 @@ events:double | pod:keyword | time_bucket:datetime avg_over_time_aggregate_metric_double_implicit_casting required_capability: ts_command_v0 required_capability: aggregate_metric_double_v0 -TS k8s* | STATS bytes = sum(avg_over_time(network.eth0.rx)) by time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, time_bucket | LIMIT 10 ; +TS k8s,k8s-downsampled | STATS bytes = sum(avg_over_time(network.eth0.rx)) by time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, time_bucket | LIMIT 10 ; bytes:double | time_bucket:datetime 8785.733333333334 | 2024-05-10T00:20:00.000Z @@ -267,7 +267,7 @@ bytes:double | time_bucket:datetime avg_over_time_aggregate_metric_double_implicit_casting_grouping required_capability: ts_command_v0 required_capability: aggregate_metric_double_v0 -TS k8s* | STATS bytes = sum(avg_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, pod, time_bucket | LIMIT 10 ; +TS k8s,k8s-downsampled | STATS bytes = sum(avg_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, pod, time_bucket | LIMIT 10 ; bytes:double | pod:keyword | time_bucket:datetime 3095.5 | one | 2024-05-10T00:20:00.000Z diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-count-over-time.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-count-over-time.csv-spec index 447e6d90716b6..c08c4ee8b6a2e 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-count-over-time.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-count-over-time.csv-spec @@ -730,7 +730,7 @@ events:double | step:datetime | pod:keyword count_over_time_aggregate_metric_double_implicit_casting required_capability: ts_command_v0 required_capability: aggregate_metric_double_v0 -TS k8s* | STATS bytes = sum(count_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes, pod, time_bucket | LIMIT 10 ; +TS k8s,k8s-downsampled | STATS bytes = sum(count_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes, pod, time_bucket | LIMIT 10 ; bytes:long | pod:keyword | time_bucket:datetime 7 | two | 2024-05-10T00:20:00.000Z @@ -750,7 +750,7 @@ count_over_time_aggregate_metric_double_implicit_casting_promql-Ignore required_capability: promql_command_v0 required_capability: aggregate_metric_double_v0 -PROMQL index=k8s* step=10m bytes=(sum by (pod) (count_over_time(network.eth0.rx[10m]))) +PROMQL index=k8s,k8s-downsampled step=10m bytes=(sum by (pod) (count_over_time(network.eth0.rx[10m]))) | SORT bytes, pod, step | LIMIT 10; bytes:double | step:datetime | pod:keyword diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-max-over-time.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-max-over-time.csv-spec index f00979a36a386..52e0075dde553 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-max-over-time.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-max-over-time.csv-spec @@ -742,7 +742,7 @@ events:double | step:datetime | pod:keyword max_over_time_aggregate_metric_double_implicit_casting required_capability: ts_command_v0 required_capability: aggregate_metric_double_v0 -TS k8s* | STATS bytes = sum(max_over_time(network.eth0.rx)) by time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, time_bucket | LIMIT 10 ; +TS k8s,k8s-downsampled | STATS bytes = sum(max_over_time(network.eth0.rx)) by time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, time_bucket | LIMIT 10 ; bytes:double | time_bucket:datetime 9058.0 | 2024-05-10T00:20:00.000Z @@ -758,7 +758,7 @@ max_over_time_aggregate_metric_double_implicit_casting_promql-Ignore required_capability: promql_command_v0 required_capability: aggregate_metric_double_v0 -PROMQL index=k8s* step=10m bytes=(sum(max_over_time(network.eth0.rx[10m]))) +PROMQL index=k8s,k8s-downsampled step=10m bytes=(sum(max_over_time(network.eth0.rx[10m]))) | SORT bytes DESC, step | LIMIT 10; bytes:double | step:datetime @@ -773,7 +773,7 @@ bytes:double | step:datetime max_over_time_aggregate_metric_double_implicit_casting_grouping required_capability: ts_command_v0 required_capability: aggregate_metric_double_v0 -TS k8s* | STATS bytes = sum(max_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, pod, time_bucket | LIMIT 10 ; +TS k8s,k8s-downsampled | STATS bytes = sum(max_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, pod, time_bucket | LIMIT 10 ; bytes:double | pod:keyword | time_bucket:datetime 3156.0 | one | 2024-05-10T00:20:00.000Z @@ -793,7 +793,7 @@ max_over_time_aggregate_metric_double_implicit_casting_grouping_promql-Ignore required_capability: promql_command_v0 required_capability: aggregate_metric_double_v0 -PROMQL index=k8s* step=10m bytes=(sum by (pod) (max_over_time(network.eth0.rx[10m]))) +PROMQL index=k8s,k8s-downsampled step=10m bytes=(sum by (pod) (max_over_time(network.eth0.rx[10m]))) | SORT bytes DESC, pod, step | LIMIT 10; bytes:double | step:datetime | pod:keyword diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-min-over-time.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-min-over-time.csv-spec index 864f1c67d1b14..ef0d2d8cf72c8 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-min-over-time.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-min-over-time.csv-spec @@ -760,7 +760,7 @@ events:double | step:datetime | pod:keyword min_over_time_aggregate_metric_double_implicit_casting required_capability: ts_command_v0 required_capability: aggregate_metric_double_v0 -TS k8s* | STATS bytes = sum(min_over_time(network.eth0.rx)) by time_bucket = bucket(@timestamp, 10minute) | SORT bytes, time_bucket | LIMIT 10 ; +TS k8s,k8s-downsampled | STATS bytes = sum(min_over_time(network.eth0.rx)) by time_bucket = bucket(@timestamp, 10minute) | SORT bytes, time_bucket | LIMIT 10 ; bytes:double | time_bucket:datetime 535.0 | 2024-05-10T00:00:00.000Z @@ -776,7 +776,7 @@ min_over_time_aggregate_metric_double_implicit_casting_promql-Ignore required_capability: promql_command_v0 required_capability: aggregate_metric_double_v0 -PROMQL index=k8s* step=10m bytes=(sum by (pod) (min_over_time(network.eth0.rx[10m]))) +PROMQL index=k8s,k8s-downsampled step=10m bytes=(sum by (pod) (min_over_time(network.eth0.rx[10m]))) | SORT bytes, pod, step | LIMIT 10; bytes:double | step:datetime | pod:keyword @@ -795,7 +795,7 @@ bytes:double | step:datetime | pod:keyword min_over_time_aggregate_metric_double_implicit_casting_grouping required_capability: ts_command_v0 required_capability: aggregate_metric_double_v0 -TS k8s* | STATS bytes = sum(min_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes, pod, time_bucket | LIMIT 10 ; +TS k8s,k8s-downsampled | STATS bytes = sum(min_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes, pod, time_bucket | LIMIT 10 ; bytes:double | pod:keyword | time_bucket:datetime 114.0 | two | 2024-05-10T00:00:00.000Z @@ -815,7 +815,7 @@ min_over_time_aggregate_metric_double_implicit_casting_grouping_promql-Ignore required_capability: promql_command_v0 required_capability: aggregate_metric_double_v0 -PROMQL index=k8s* step=10m bytes=(sum by (pod) (min_over_time(network.eth0.rx[10m]))) +PROMQL index=k8s,k8s-downsampled step=10m bytes=(sum by (pod) (min_over_time(network.eth0.rx[10m]))) | SORT bytes, pod, step | LIMIT 10; bytes:double | step:datetime | pod:keyword diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-sum-over-time.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-sum-over-time.csv-spec index dd51ad54950c3..3c4cbccbc9e4d 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-sum-over-time.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-sum-over-time.csv-spec @@ -430,7 +430,7 @@ events:double | step:datetime | pod:keyword sum_over_time_aggregate_metric_double_implicit_casting required_capability: ts_command_v0 required_capability: aggregate_metric_double_v0 -TS k8s* | STATS bytes = sum(sum_over_time(network.eth0.rx)) by time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, time_bucket | LIMIT 10 ; +TS k8s,k8s-downsampled | STATS bytes = sum(sum_over_time(network.eth0.rx)) by time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, time_bucket | LIMIT 10 ; bytes:double | time_bucket:datetime 69195.0 | 2024-05-10T00:10:00.000Z @@ -446,7 +446,7 @@ sum_over_time_aggregate_metric_double_implicit_casting_promql-Ignore required_capability: promql_command_v0 required_capability: aggregate_metric_double_v0 -PROMQL index=k8s* step=10m bytes=(sum(sum_over_time(network.eth0.rx[10m]))) +PROMQL index=k8s,k8s-downsampled step=10m bytes=(sum(sum_over_time(network.eth0.rx[10m]))) | SORT bytes desc, step | LIMIT 10; bytes:double | step:datetime @@ -461,7 +461,7 @@ bytes:double | step:datetime sum_over_time_aggregate_metric_double_implicit_casting_grouping required_capability: ts_command_v0 required_capability: aggregate_metric_double_v0 -TS k8s* | STATS bytes = sum(sum_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, pod, time_bucket | LIMIT 10 ; +TS k8s,k8s-downsampled | STATS bytes = sum(sum_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, pod, time_bucket | LIMIT 10 ; bytes:double | pod:keyword | time_bucket:datetime 25245.0 | one | 2024-05-10T00:10:00.000Z @@ -481,7 +481,7 @@ sum_over_time_aggregate_metric_double_implicit_casting_grouping_promql-Ignore required_capability: promql_command_v0 required_capability: aggregate_metric_double_v0 -PROMQL index=k8s* step=10m bytes=(sum by (pod) (sum_over_time(network.eth0.rx[10m]))) +PROMQL index=k8s,k8s-downsampled step=10m bytes=(sum by (pod) (sum_over_time(network.eth0.rx[10m]))) | SORT bytes desc, pod, step | LIMIT 10; bytes:double | step:datetime | pod:keyword diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries.csv-spec index 4d60da9739587..5be39da04be02 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries.csv-spec @@ -1318,7 +1318,7 @@ max:double | std_dev:double | pod:keyword DefaultMetricWithFromImplicitCasting required_capability: ts_command_v0 required_capability: aggregate_metric_double_avg_as_default_metric -FROM k8s* +FROM k8s,k8s-downsampled | STATS min = min(network.eth0.tx), std_dev = ROUND(STD_DEV(network.eth0.tx), 7) by pod | sort pod ; @@ -1332,7 +1332,7 @@ min:double | std_dev:double | pod:keyword DefaultMetricWithTSImplicitCasting required_capability: ts_command_v0 required_capability: aggregate_metric_double_avg_as_default_metric -TS k8s* +TS k8s,k8s-downsampled | STATS min = min(network.eth0.tx), max = max(network.eth0.tx), std_dev = ROUND(STD_DEV(network.eth0.tx), 7) by pod | sort pod ; 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 f5b77ebee8259..b7a603d94724b 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 @@ -5044,7 +5044,7 @@ public void testImplicitCastingForAggregateMetricDouble() { ); var esIndex = new EsIndex( - "k8s*", + "k8s,k8s-downsampled", mapping, Map.of("k8s", IndexMode.TIME_SERIES, "k8s-downsampled", IndexMode.TIME_SERIES), Map.of(), @@ -5062,12 +5062,12 @@ public void testImplicitCastingForAggregateMetricDouble() { TEST_VERIFIER ); var stddevPlan = analyze(""" - from k8s* | stats std_dev = std_dev(metric_field) + from k8s,k8s-downsampled | stats std_dev = std_dev(metric_field) """, analyzer); assertProjection(stddevPlan, "std_dev"); var plan = analyze(""" - from k8s* | stats max = max(metric_field), + from k8s,k8s-downsampled | stats max = max(metric_field), avg = avg(metric_field), sum = sum(metric_field), min = min(metric_field), @@ -5076,7 +5076,7 @@ public void testImplicitCastingForAggregateMetricDouble() { assertProjection(plan, "max", "avg", "sum", "min", "count"); var plan2 = analyze(""" - TS k8s* | stats s1 = sum(sum_over_time(metric_field)), + TS k8s,k8s-downsampled | stats s1 = sum(sum_over_time(metric_field)), s2 = sum(avg_over_time(metric_field)), min = min(max_over_time(metric_field)), count = count(count_over_time(metric_field)), From bb62330e7949ad4680b55ae8bf7f890cf39053ed Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 5 Mar 2026 17:55:41 +0200 Subject: [PATCH 095/137] Update docs/changelog/143693.yaml --- docs/changelog/143693.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 docs/changelog/143693.yaml diff --git a/docs/changelog/143693.yaml b/docs/changelog/143693.yaml new file mode 100644 index 0000000000000..a9328ab62bd39 --- /dev/null +++ b/docs/changelog/143693.yaml @@ -0,0 +1,5 @@ +area: ES|QL +issues: [] +pr: 143693 +summary: Type conflict resolution in unmapped-fields load +type: feature From 0853edaeed649f0c833480997f916f44102e446e Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Thu, 5 Mar 2026 16:06:44 +0000 Subject: [PATCH 096/137] [CI] Auto commit changes from spotless --- .../xpack/esql/analysis/AnalyzerTests.java | 1 - .../analysis/AnalyzerUnmappedGoldenTests.java | 24 +++++++------------ .../xpack/esql/index/EsIndexGenerator.java | 1 - .../xpack/esql/optimizer/GoldenTestCase.java | 1 + .../AbstractPromqlPlanOptimizerTests.java | 1 - .../PromqlLogicalPlanOptimizerTests.java | 1 - .../TimeSeriesBareAggregationsTests.java | 1 - 7 files changed, 10 insertions(+), 20 deletions(-) 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 97350842becf9..5d1d538f7f04f 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 @@ -125,7 +125,6 @@ import org.elasticsearch.xpack.esql.session.IndexResolver; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.time.Instant; import java.time.Period; import java.util.ArrayList; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java index 54807f1997e9b..2ab938e3ca66c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -387,13 +387,10 @@ public void testTBucketAggregateUnmapped() throws Exception { } public void testTimeSeriesRateUnmapped() throws Exception { - runTestsNullifyOnly( - """ - TS k8s - | STATS r = RATE(does_not_exist) BY tbucket(1 hour) - """, - STAGES - ); + runTestsNullifyOnly(""" + TS k8s + | STATS r = RATE(does_not_exist) BY tbucket(1 hour) + """, STAGES); } public void testTimeSeriesFirstOverTimeUnmapped() throws Exception { @@ -432,14 +429,11 @@ public void testMappedToNonKeywordInOneIndexOnly() throws Exception { } public void testMappedToNonKeywordInOneIndexOnlyCast() throws Exception { - runTestsLoadOnly( - """ - FROM sample_data, no_mapping_sample_data - | EVAL event_duration = event_duration :: DOUBLE - | KEEP event_duration - """, - EnumSet.of(Stage.ANALYSIS, Stage.LOGICAL_OPTIMIZATION, Stage.PHYSICAL_OPTIMIZATION, Stage.LOCAL_PHYSICAL_OPTIMIZATION) - ); + runTestsLoadOnly(""" + FROM sample_data, no_mapping_sample_data + | EVAL event_duration = event_duration :: DOUBLE + | KEEP event_duration + """, EnumSet.of(Stage.ANALYSIS, Stage.LOGICAL_OPTIMIZATION, Stage.PHYSICAL_OPTIMIZATION, Stage.LOCAL_PHYSICAL_OPTIMIZATION)); } public void testDifferentTypesAndUnmapped() throws Exception { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/index/EsIndexGenerator.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/index/EsIndexGenerator.java index d59b82f8b905c..2a686260e804a 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/index/EsIndexGenerator.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/index/EsIndexGenerator.java @@ -15,7 +15,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import static org.elasticsearch.core.Tuple.tuple; import static org.elasticsearch.test.ESTestCase.randomFrom; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java index ac9913ff1eaf1..30de6f9c2d549 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/GoldenTestCase.java @@ -421,6 +421,7 @@ private static String normalizeNameIds(String planString) { return "#" + idMap.getId(originalId); }); } + /** * Normalizes synthetic attribute names of the form $$something($something)* that are followed by # (node id). * Replaces them with $$firstSegment$runningInt so golden output is stable across runs. diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/AbstractPromqlPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/AbstractPromqlPlanOptimizerTests.java index c826b908491d2..68bfe14029bac 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/AbstractPromqlPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/AbstractPromqlPlanOptimizerTests.java @@ -32,7 +32,6 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Map; -import java.util.Set; import static java.util.Collections.emptyMap; import static org.elasticsearch.xpack.esql.EsqlTestUtils.TEST_VERIFIER; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/PromqlLogicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/PromqlLogicalPlanOptimizerTests.java index d9c37697dec27..da810dd62dd34 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/PromqlLogicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/PromqlLogicalPlanOptimizerTests.java @@ -65,7 +65,6 @@ import java.time.temporal.ChronoUnit; import java.util.List; import java.util.Map; -import java.util.Set; import static java.util.Collections.emptyMap; import static org.elasticsearch.xpack.esql.EsqlTestUtils.TEST_VERIFIER; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/TimeSeriesBareAggregationsTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/TimeSeriesBareAggregationsTests.java index af1b8c0b867e2..116e4fc3d319b 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/TimeSeriesBareAggregationsTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/TimeSeriesBareAggregationsTests.java @@ -31,7 +31,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import static org.elasticsearch.xpack.esql.EsqlTestUtils.TEST_VERIFIER; import static org.elasticsearch.xpack.esql.EsqlTestUtils.emptyInferenceResolution; From 7ae894ed5719bf25048ab70c770dfadd0abe4f37 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 10 Mar 2026 20:45:28 +0200 Subject: [PATCH 097/137] some renames --- .../analysis/AnalyzerUnmappedGoldenTests.java | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java index 2ab938e3ca66c..1a6df4a6b1730 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -22,8 +22,7 @@ public class AnalyzerUnmappedGoldenTests extends UnmappedGoldenTestCase { public void testKeep() throws Exception { runTests(""" FROM employees - | eval x = does_not_exist_field :: version - | keep x + | keep does_not_exist_field """); } @@ -119,14 +118,14 @@ public void testMultipleEval() throws Exception { """); } - public void testEvalCast() throws Exception { + public void testCasting() throws Exception { runTests(""" FROM employees | EVAL x = does_not_exist_field::LONG """); } - public void testEvalCastInPlace() throws Exception { + public void testCastingNoAliasing() throws Exception { runTests(""" FROM employees | EVAL does_not_exist_field::LONG @@ -149,14 +148,14 @@ public void testKeepThenEval() throws Exception { """); } - public void testStatsCount() throws Exception { + public void testStatsAgg() throws Exception { runTests(""" FROM employees | STATS cnt = COUNT(does_not_exist_field) """); } - public void testStatsBy() throws Exception { + public void testStatsGroup() throws Exception { runTests(""" FROM employees | STATS BY does_not_exist_field @@ -171,35 +170,35 @@ public void testDoesNotExistAfterInlineStats() throws Exception { """); } - public void testStatsSumBy() throws Exception { + public void testStatsAggAndGroup() throws Exception { runTests(""" FROM employees | STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 """); } - public void testStatsSumByMultiple() throws Exception { + public void testStatsAggAndAliasGroup() throws Exception { runTests(""" FROM employees | STATS s = SUM(does_not_exist1::DOUBLE) + d2 BY d2 = does_not_exist2::DOUBLE, emp_no """); } - public void testStatsSumByComplex() throws Exception { + public void testStatsAggAndAliasedGroupedWithExpression() throws Exception { runTests(""" FROM employees | STATS sum = SUM(does_not_exist1::DOUBLE) + s0 + s1 BY s0 = does_not_exist2::DOUBLE + does_not_exist3::DOUBLE, s1 = emp_no """); } - public void testStatsMultiple() throws Exception { + public void testStatsMixed() throws Exception { runTests(""" FROM employees | STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no """); } - public void testInlineStats() throws Exception { + public void testInlineStatsMixed() throws Exception { runTests(""" FROM employees | INLINE STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no @@ -227,14 +226,14 @@ public void testWhereComplex() throws Exception { """); } - public void testStatsCountWhere() throws Exception { + public void testStatsAggFiltering() throws Exception { runTests(""" FROM employees | STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 """); } - public void testStatsMultipleCountWhere() throws Exception { + public void testAggsFilteringMultipleFields() throws Exception { runTests(""" FROM employees | STATS c1 = COUNT(*) WHERE does_not_exist1::LONG > 0 OR emp_no > 0 OR does_not_exist2::LONG < 100, @@ -256,7 +255,7 @@ public void testSortExpression() throws Exception { """); } - public void testSortMultiple() throws Exception { + public void testSortExpressionMultipleFields() throws Exception { runTests(""" FROM employees | SORT does_not_exist1::LONG + 1, does_not_exist2 DESC, emp_no ASC @@ -270,6 +269,7 @@ public void testMvExpand() throws Exception { """); } + // FIXME comment here but keep the test public void testLookupJoin() throws Exception { runTests(""" FROM employees @@ -278,6 +278,7 @@ public void testLookupJoin() throws Exception { """); } + // FIXME comment here but keep the test public void testLookupJoinWithFilter() throws Exception { runTests(""" FROM employees @@ -287,6 +288,7 @@ public void testLookupJoinWithFilter() throws Exception { """); } + // FIXME comment here but keep the test public void testSubqueryKeepUnmapped() throws Exception { runTests(""" FROM employees, (FROM languages | KEEP language_code) @@ -294,6 +296,7 @@ public void testSubqueryKeepUnmapped() throws Exception { """); } + // FIXME comment here but keep the test public void testSubqueryWithStats() throws Exception { runTests(""" FROM employees, (FROM sample_data | STATS max_ts = MAX(@timestamp) BY does_not_exist) @@ -301,6 +304,7 @@ public void testSubqueryWithStats() throws Exception { """); } + // FIXME comment here but keep the test public void testSubqueryKeepMultipleUnmapped() throws Exception { runTests(""" FROM employees, @@ -309,6 +313,7 @@ public void testSubqueryKeepMultipleUnmapped() throws Exception { """); } + // FIXME comment here but keep the test public void testFork() throws Exception { runTests(""" FROM employees @@ -325,6 +330,7 @@ public void testForkWithEval() throws Exception { """); } + // FIXME comment here but keep the test public void testForkWithStats() throws Exception { runTests(""" FROM employees @@ -334,6 +340,7 @@ public void testForkWithStats() throws Exception { """); } + // FIXME comment here but keep the test public void testFuse() throws Exception { assumeTrue("requires FUSE capability", EsqlCapabilities.Cap.FUSE_V6.isEnabled()); runTests(""" @@ -344,6 +351,7 @@ public void testFuse() throws Exception { """); } + // FIXME comment here but keep the test public void testFuseWithEval() throws Exception { assumeTrue("requires FUSE capability", EsqlCapabilities.Cap.FUSE_V6.isEnabled()); runTests(""" @@ -354,6 +362,7 @@ public void testFuseWithEval() throws Exception { """); } + // FIXME comment here but keep the test public void testFuseLinear() throws Exception { assumeTrue("requires FUSE capability", EsqlCapabilities.Cap.FUSE_V6.isEnabled()); runTests(""" From 3adf6bef49c6bdcfa90dddfed20c2be2d242ede1 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Sun, 15 Mar 2026 19:25:13 +0200 Subject: [PATCH 098/137] Remove golden orphans --- .../load/analysis.expected | 3 --- .../load/query.esql | 2 -- .../nullify/analysis.expected | 4 ---- .../nullify/query.esql | 2 -- .../load/analysis.expected | 3 --- .../load/query.esql | 2 -- .../nullify/analysis.expected | 3 --- .../nullify/query.esql | 2 -- .../load/analysis.expected | 4 ---- .../load/query.esql | 2 -- .../nullify/analysis.expected | 4 ---- .../nullify/query.esql | 2 -- .../load/analysis.expected | 4 ---- .../load/query.esql | 3 --- .../nullify/analysis.expected | 4 ---- .../nullify/query.esql | 3 --- .../load/analysis.expected | 5 ---- .../load/query.esql | 3 --- .../nullify/analysis.expected | 6 ----- .../nullify/query.esql | 3 --- .../testDrop/load/analysis.expected | 3 --- .../testDrop/load/query.esql | 2 -- .../testDrop/nullify/analysis.expected | 4 ---- .../testDrop/nullify/query.esql | 2 -- .../load/analysis.expected | 3 --- .../testDropAndMatchingStar/load/query.esql | 2 -- .../nullify/analysis.expected | 4 ---- .../nullify/query.esql | 2 -- .../testEvalCast/load/analysis.expected | 3 --- .../testEvalCast/load/query.esql | 2 -- .../testEvalCast/nullify/analysis.expected | 4 ---- .../testEvalCast/nullify/query.esql | 2 -- .../load/analysis.expected | 3 --- .../testEvalCastInPlace/load/query.esql | 2 -- .../nullify/analysis.expected | 4 ---- .../testEvalCastInPlace/nullify/query.esql | 2 -- .../testEvalReplace/load/analysis.expected | 4 ---- .../testEvalReplace/load/query.esql | 3 --- .../testEvalReplace/nullify/analysis.expected | 5 ---- .../testEvalReplace/nullify/query.esql | 3 --- .../testFork/load/analysis.expected | 13 ----------- .../testFork/load/query.esql | 3 --- .../testForkWithEval/load/analysis.expected | 14 ----------- .../testForkWithEval/load/query.esql | 3 --- .../testForkWithSort/load/analysis.expected | 19 --------------- .../testForkWithSort/load/query.esql | 4 ---- .../nullify/analysis.expected | 21 ----------------- .../testForkWithSort/nullify/query.esql | 4 ---- .../testForkWithStats/load/analysis.expected | 15 ------------ .../testForkWithStats/load/query.esql | 4 ---- .../testFuse/load/analysis.expected | 15 ------------ .../testFuse/load/query.esql | 4 ---- .../testFuseLinear/load/analysis.expected | 18 --------------- .../testFuseLinear/load/query.esql | 4 ---- .../testFuseWithEval/load/analysis.expected | 16 ------------- .../testFuseWithEval/load/query.esql | 4 ---- .../testKeepThenEval/load/analysis.expected | 4 ---- .../testKeepThenEval/load/query.esql | 3 --- .../nullify/analysis.expected | 5 ---- .../testKeepThenEval/nullify/query.esql | 3 --- .../testLookupJoin/load/analysis.expected | 5 ---- .../testLookupJoin/load/query.esql | 3 --- .../load/analysis.expected | 6 ----- .../testLookupJoinWithEval/load/query.esql | 4 ---- .../nullify/analysis.expected | 7 ------ .../testLookupJoinWithEval/nullify/query.esql | 4 ---- .../load/analysis.expected | 6 ----- .../testLookupJoinWithFilter/load/query.esql | 4 ---- .../load/analysis.expected | 4 ---- .../load/local_physical_optimization.expected | 6 ----- .../load/logical_optimization.expected | 3 --- .../load/physical_optimization.expected | 7 ------ .../load/query.esql | 3 --- .../nullify/analysis.expected | 3 --- .../nullify/query.esql | 2 -- .../load/analysis.expected | 4 ---- .../load/query.esql | 3 --- .../nullify/analysis.expected | 5 ---- .../nullify/query.esql | 3 --- .../load/analysis.expected | 3 --- .../load/query.esql | 2 -- .../nullify/analysis.expected | 4 ---- .../nullify/query.esql | 2 -- .../testRenameEval/load/analysis.expected | 4 ---- .../testRenameEval/load/query.esql | 3 --- .../testRenameEval/nullify/analysis.expected | 5 ---- .../testRenameEval/nullify/query.esql | 3 --- .../testRenameRepeated/load/analysis.expected | 3 --- .../testRenameRepeated/load/query.esql | 2 -- .../nullify/analysis.expected | 4 ---- .../testRenameRepeated/nullify/query.esql | 2 -- .../testRow/load/query.esql | 3 --- .../testSortMultiple/load/analysis.expected | 3 --- .../testSortMultiple/load/query.esql | 2 -- .../nullify/analysis.expected | 4 ---- .../testSortMultiple/nullify/query.esql | 2 -- .../load/analysis.expected | 3 --- .../testStatsAggFiltering/load/query.esql | 2 -- .../nullify/analysis.expected | 4 ---- .../testStatsAggFiltering/nullify/query.esql | 2 -- .../testStatsBy/load/analysis.expected | 3 --- .../testStatsBy/load/query.esql | 2 -- .../testStatsBy/nullify/analysis.expected | 4 ---- .../testStatsBy/nullify/query.esql | 2 -- .../testStatsCount/load/analysis.expected | 3 --- .../testStatsCount/load/query.esql | 2 -- .../testStatsCount/nullify/analysis.expected | 4 ---- .../testStatsCount/nullify/query.esql | 2 -- .../load/analysis.expected | 3 --- .../testStatsCountWhere/load/query.esql | 2 -- .../nullify/analysis.expected | 4 ---- .../testStatsCountWhere/nullify/query.esql | 2 -- .../testStatsMultiple/load/analysis.expected | 3 --- .../testStatsMultiple/load/query.esql | 2 -- .../nullify/analysis.expected | 4 ---- .../testStatsMultiple/nullify/query.esql | 2 -- .../load/analysis.expected | 3 --- .../load/query.esql | 3 --- .../nullify/analysis.expected | 4 ---- .../nullify/query.esql | 3 --- .../testStatsSumBy/load/analysis.expected | 3 --- .../testStatsSumBy/load/query.esql | 2 -- .../testStatsSumBy/nullify/analysis.expected | 4 ---- .../testStatsSumBy/nullify/query.esql | 2 -- .../load/analysis.expected | 3 --- .../testStatsSumByComplex/load/query.esql | 2 -- .../nullify/analysis.expected | 4 ---- .../testStatsSumByComplex/nullify/query.esql | 2 -- .../load/analysis.expected | 3 --- .../testStatsSumByMultiple/load/query.esql | 2 -- .../nullify/analysis.expected | 4 ---- .../testStatsSumByMultiple/nullify/query.esql | 2 -- .../testSubquery/load/analysis.expected | 11 --------- .../testSubquery/load/query.esql | 2 -- .../testSubquery/nullify/analysis.expected | 12 ---------- .../testSubquery/nullify/query.esql | 2 -- .../testSubqueryKeep/load/query.esql | 3 --- .../testSubqueryKeep/nullify/query.esql | 3 --- .../load/analysis.expected | 11 --------- .../load/query.esql | 3 --- .../load/analysis.expected | 13 ----------- .../testSubqueryKeepUnmapped/load/query.esql | 2 -- .../load/analysis.expected | 21 ----------------- .../load/query.esql | 5 ---- .../nullify/analysis.expected | 23 ------------------- .../nullify/query.esql | 5 ---- .../load/analysis.expected | 11 --------- .../testSubqueryWithStats/load/query.esql | 2 -- .../testTBucket/load/analysis.expected | 4 ---- .../testTBucket/load/query.esql | 3 --- .../testTBucket/nullify/analysis.expected | 5 ---- .../testTBucket/nullify/query.esql | 3 --- .../load/query.esql | 2 -- .../nullify/query.esql | 2 -- .../load/analysis.expected | 3 --- .../load/query.esql | 2 -- .../nullify/analysis.expected | 4 ---- .../nullify/query.esql | 2 -- .../load/analysis.expected | 4 ---- .../testTimeSeriesAvgOverTime/load/query.esql | 3 --- .../nullify/analysis.expected | 5 ---- .../nullify/query.esql | 3 --- .../load/analysis.expected | 4 ---- .../load/query.esql | 3 --- .../nullify/analysis.expected | 5 ---- .../nullify/query.esql | 3 --- .../load/analysis.expected | 3 --- .../load/query.esql | 2 -- .../nullify/analysis.expected | 4 ---- .../nullify/query.esql | 2 -- .../load/analysis.expected | 4 ---- .../testTimeSeriesMaxOverTime/load/query.esql | 3 --- .../nullify/analysis.expected | 5 ---- .../nullify/query.esql | 3 --- .../testTimeSeriesRate/load/analysis.expected | 4 ---- .../testTimeSeriesRate/load/query.esql | 3 --- .../nullify/analysis.expected | 5 ---- .../testTimeSeriesRate/nullify/query.esql | 3 --- .../nullify/query.esql | 2 -- 179 files changed, 765 deletions(-) delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/local_physical_optimization.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/logical_optimization.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/physical_optimization.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRow/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateWithUnmappedGroupBy/nullify/query.esql diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected deleted file mode 100644 index fa51740222109..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[!@timestamp, message{f(KeywordEsField)}#0, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#1]] - \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#2, event_duration{f}#3, message{f}#0, does_not_exist{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/query.esql deleted file mode 100644 index f8a423e9c25b6..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM sample_data, sample_data_ts_long -| KEEP @timestamp, message, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected deleted file mode 100644 index b20e372050ebe..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[!@timestamp, message{f(KeywordEsField)}#0, does_not_exist{r}#1]] - \_Eval[[null[NULL] AS does_not_exist#1]] - \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#2, event_duration{f}#3, message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/query.esql deleted file mode 100644 index 4336bd5f39d8e..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAcrossIndices/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM sample_data, sample_data_ts_long -| KEEP @timestamp, message, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/analysis.expected deleted file mode 100644 index 338fc3701e44c..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[!@timestamp]] - \_EsRelation[sample_data,sample_data_ts_long,no_mapping_sample_data][!@timestamp, client_ip{f}#0, event_duration{f}#1, message{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/query.esql deleted file mode 100644 index 1e55cfb1096c9..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM sample_data, sample_data_ts_long, no_mapping_sample_data -| KEEP @timestamp diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/analysis.expected deleted file mode 100644 index 338fc3701e44c..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[!@timestamp]] - \_EsRelation[sample_data,sample_data_ts_long,no_mapping_sample_data][!@timestamp, client_ip{f}#0, event_duration{f}#1, message{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/query.esql deleted file mode 100644 index 75305542ab2b0..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmapped/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM sample_data, sample_data_ts_long, no_mapping_sample_data -| KEEP @timestamp diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/analysis.expected deleted file mode 100644 index 1f2cf5e16ad87..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Project[[!@timestamp, client_ip{f(EsField)}#0, event_duration{f(EsField)}#1, message{f(KeywordEsField)}#2, x{r}#3]] -\_Limit[1000[INTEGER],false,false] - \_Eval[[$$@timestamp$converted_to$double{f(MultiTypeEsField)$}#4 AS x#3]] - \_EsRelation[sample_data,sample_data_ts_long,no_mapping_sample_data][!@timestamp, client_ip{f}#0, event_duration{f}#1, message{f}#2, $$@timestamp$converted_to$double{f$}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/query.esql deleted file mode 100644 index b6749814f782a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM sample_data, sample_data_ts_long, no_mapping_sample_data -| EVAL x = @timestamp :: DOUBLE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/analysis.expected deleted file mode 100644 index 1f2cf5e16ad87..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Project[[!@timestamp, client_ip{f(EsField)}#0, event_duration{f(EsField)}#1, message{f(KeywordEsField)}#2, x{r}#3]] -\_Limit[1000[INTEGER],false,false] - \_Eval[[$$@timestamp$converted_to$double{f(MultiTypeEsField)$}#4 AS x#3]] - \_EsRelation[sample_data,sample_data_ts_long,no_mapping_sample_data][!@timestamp, client_ip{f}#0, event_duration{f}#1, message{f}#2, $$@timestamp$converted_to$double{f$}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/query.esql deleted file mode 100644 index e486841e2f785..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesAndUnmappedCast/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM sample_data, sample_data_ts_long, no_mapping_sample_data -| EVAL x = @timestamp :: DOUBLE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected deleted file mode 100644 index 4e22cfb0e1b0c..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[ts{r}#0, message{f(KeywordEsField)}#1, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2]] - \_Eval[[$$@timestamp$converted_to$keyword{f(MultiTypeEsField)$}#3 AS ts#0]] - \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#4, event_duration{f}#5, message{f}#1, $$@timestamp$converted_to$keyword{f$}#3, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/query.esql deleted file mode 100644 index 1ac50de7de6cd..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM sample_data, sample_data_ts_long -| EVAL ts = @timestamp::STRING -| KEEP ts, message, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected deleted file mode 100644 index f280fa143e76e..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[ts{r}#0, message{f(KeywordEsField)}#1, does_not_exist{r}#2]] - \_Eval[[$$@timestamp$converted_to$keyword{f(MultiTypeEsField)$}#3 AS ts#0, null[NULL] AS does_not_exist#2]] - \_EsRelation[sample_data,sample_data_ts_long][!@timestamp, client_ip{f}#4, event_duration{f}#5, message{f}#1, $$@timestamp$converted_to$keyword{f$}#3] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql deleted file mode 100644 index ba866b39d02b5..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDifferentTypesWithCast/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; FROM sample_data, sample_data_ts_long, employees -| EVAL ts = @timestamp::STRING -| KEEP ts, message, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/analysis.expected deleted file mode 100644 index 13558bfef2002..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0 AS x#1]] - \_InlineStats[] - \_Aggregate[[emp_no{f(EsField)}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS COUNT(*)#3, emp_no{f(EsField)}#2]] - \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/query.esql deleted file mode 100644 index 4148af41e94f6..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| INLINE STATS COUNT(*) BY emp_no -| EVAL x = does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/analysis.expected deleted file mode 100644 index bbfb54572a2cb..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/analysis.expected +++ /dev/null @@ -1,6 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[does_not_exist_field{r}#0 AS x#1]] - \_InlineStats[] - \_Aggregate[[emp_no{f(EsField)}#2],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS COUNT(*)#3, emp_no{f(EsField)}#2]] - \_Eval[[null[NULL] AS does_not_exist_field#0]] - \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#2, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/query.esql deleted file mode 100644 index 98bbe99592e9a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDoesNotExistAfterStats/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| STATS COUNT(*) BY emp_no -| EVAL x = salary diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected deleted file mode 100644 index acd024f56f58a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, first_name{f(KeywordEsField)}#2, gender{f(KeywordEsField)}#3, height{f(EsField)}#4, height.float{f(EsField)}#5, height.half_float{f(EsField)}#6, height.scaled_float{f(EsField)}#7, hire_date{f(DateEsField)}#8, is_rehired{f(EsField)}#9, job_positions{f(KeywordEsField)}#10, languages{f(EsField)}#11, languages.byte{f(EsField)}#12, languages.long{f(EsField)}#13, languages.short{f(EsField)}#14, last_name{f(KeywordEsField)}#15, salary{f(EsField)}#16, salary_change{f(EsField)}#17, salary_change.int{f(EsField)}#18, salary_change.keyword{f(KeywordEsField)}#19, salary_change.long{f(EsField)}#20, still_hired{f(EsField)}#21]] - \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#22, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21, does_not_exist_field{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/query.esql deleted file mode 100644 index 4651e798553a5..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| DROP does_not_exist_field, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected deleted file mode 100644 index 9b31329838788..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, first_name{f(KeywordEsField)}#2, gender{f(KeywordEsField)}#3, height{f(EsField)}#4, height.float{f(EsField)}#5, height.half_float{f(EsField)}#6, height.scaled_float{f(EsField)}#7, hire_date{f(DateEsField)}#8, is_rehired{f(EsField)}#9, job_positions{f(KeywordEsField)}#10, languages{f(EsField)}#11, languages.byte{f(EsField)}#12, languages.long{f(EsField)}#13, languages.short{f(EsField)}#14, last_name{f(KeywordEsField)}#15, salary{f(EsField)}#16, salary_change{f(EsField)}#17, salary_change.int{f(EsField)}#18, salary_change.keyword{f(KeywordEsField)}#19, salary_change.long{f(EsField)}#20, still_hired{f(EsField)}#21]] - \_Eval[[null[NULL] AS does_not_exist_field#22]] - \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#23, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/query.esql deleted file mode 100644 index deb3bd1826afc..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDrop/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| DROP does_not_exist_field, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected deleted file mode 100644 index acd024f56f58a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, first_name{f(KeywordEsField)}#2, gender{f(KeywordEsField)}#3, height{f(EsField)}#4, height.float{f(EsField)}#5, height.half_float{f(EsField)}#6, height.scaled_float{f(EsField)}#7, hire_date{f(DateEsField)}#8, is_rehired{f(EsField)}#9, job_positions{f(KeywordEsField)}#10, languages{f(EsField)}#11, languages.byte{f(EsField)}#12, languages.long{f(EsField)}#13, languages.short{f(EsField)}#14, last_name{f(KeywordEsField)}#15, salary{f(EsField)}#16, salary_change{f(EsField)}#17, salary_change.int{f(EsField)}#18, salary_change.keyword{f(KeywordEsField)}#19, salary_change.long{f(EsField)}#20, still_hired{f(EsField)}#21]] - \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#22, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21, does_not_exist_field{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/query.esql deleted file mode 100644 index 0b9aa5a1c9b86..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| DROP emp_*, does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected deleted file mode 100644 index 9b31329838788..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, first_name{f(KeywordEsField)}#2, gender{f(KeywordEsField)}#3, height{f(EsField)}#4, height.float{f(EsField)}#5, height.half_float{f(EsField)}#6, height.scaled_float{f(EsField)}#7, hire_date{f(DateEsField)}#8, is_rehired{f(EsField)}#9, job_positions{f(KeywordEsField)}#10, languages{f(EsField)}#11, languages.byte{f(EsField)}#12, languages.long{f(EsField)}#13, languages.short{f(EsField)}#14, last_name{f(KeywordEsField)}#15, salary{f(EsField)}#16, salary_change{f(EsField)}#17, salary_change.int{f(EsField)}#18, salary_change.keyword{f(KeywordEsField)}#19, salary_change.long{f(EsField)}#20, still_hired{f(EsField)}#21]] - \_Eval[[null[NULL] AS does_not_exist_field#22]] - \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#23, first_name{f}#2, gender{f}#3, height{f}#4, height.float{f}#5, height.half_float{f}#6, height.scaled_float{f}#7, hire_date{f}#8, is_rehired{f}#9, job_positions{f}#10, languages{f}#11, languages.byte{f}#12, languages.long{f}#13, languages.short{f}#14, last_name{f}#15, salary{f}#16, salary_change{f}#17, salary_change.int{f}#18, salary_change.keyword{f}#19, salary_change.long{f}#20, still_hired{f}#21] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/query.esql deleted file mode 100644 index 7064d202cbedc..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testDropAndMatchingStar/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| DROP emp_*, does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected deleted file mode 100644 index 93fe00d388c1d..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[TOLONG(does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0) AS x#1]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/query.esql deleted file mode 100644 index f26a0fbca818e..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| EVAL x = does_not_exist_field::LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/analysis.expected deleted file mode 100644 index 94776e53044a1..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[TOLONG(does_not_exist_field{r}#0) AS x#1]] - \_Eval[[null[NULL] AS does_not_exist_field#0]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/query.esql deleted file mode 100644 index 645643aa1255c..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCast/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| EVAL x = does_not_exist_field::LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected deleted file mode 100644 index 1057b571c78de..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[TOLONG(does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0) AS does_not_exist_field::LONG#1]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/query.esql deleted file mode 100644 index fde7a9a40d5e3..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| EVAL does_not_exist_field::LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/analysis.expected deleted file mode 100644 index 8b534e63aaf3c..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[TOLONG(does_not_exist_field{r}#0) AS does_not_exist_field::LONG#1]] - \_Eval[[null[NULL] AS does_not_exist_field#0]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/query.esql deleted file mode 100644 index 91f24cce1fb92..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalCastInPlace/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| EVAL does_not_exist_field::LONG diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected deleted file mode 100644 index ffb2c79dd6cd0..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[42[INTEGER] AS does_not_exist_field#0]] - \_Eval[[TODOUBLE(does_not_exist_field{f}#1) + 1[INTEGER] AS x#2]] - \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/query.esql deleted file mode 100644 index 826ae0ac8f745..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| EVAL x = does_not_exist_field::DOUBLE + 1 -| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected deleted file mode 100644 index 5ce8713e6a882..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[42[INTEGER] AS does_not_exist_field#0]] - \_Eval[[TODOUBLE(does_not_exist_field{r}#1) + 1[INTEGER] AS x#2]] - \_Eval[[null[NULL] AS does_not_exist_field#1]] - \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql deleted file mode 100644 index 241e39491fa9a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| EVAL x = does_not_exist_field::DOUBLE + 1 -| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected deleted file mode 100644 index cd1fc9b47d736..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected +++ /dev/null @@ -1,13 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, _fork{r}#24]] - |_Limit[1000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f()}#25, birth_date{f()}#26, emp_no{f()}#27, first_name{f()}#28, gender{f()}#29, height{f()}#30, height.float{f()}#31, height.half_float{f()}#32, height.scaled_float{f()}#33, hire_date{f()}#34, is_rehired{f()}#35, job_positions{f()}#36, languages{f()}#37, languages.byte{f()}#38, languages.long{f()}#39, languages.short{f()}#40, last_name{f()}#41, salary{f()}#42, salary_change{f()}#43, salary_change.int{f()}#44, salary_change.keyword{f()}#45, salary_change.long{f()}#46, still_hired{f()}#47, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#48, _fork{r}#49]] - | \_Eval[[fork1[KEYWORD] AS _fork#49]] - | \_Filter[TOLONG(does_not_exist{f}#48) > 0[INTEGER]] - | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, does_not_exist{f}#48] - \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f()}#50, birth_date{f()}#51, emp_no{f()}#52, first_name{f()}#53, gender{f()}#54, height{f()}#55, height.float{f()}#56, height.half_float{f()}#57, height.scaled_float{f()}#58, hire_date{f()}#59, is_rehired{f()}#60, job_positions{f()}#61, languages{f()}#62, languages.byte{f()}#63, languages.long{f()}#64, languages.short{f()}#65, last_name{f()}#66, salary{f()}#67, salary_change{f()}#68, salary_change.int{f()}#69, salary_change.keyword{f()}#70, salary_change.long{f()}#71, still_hired{f()}#72, does_not_exist{r}#73, _fork{r}#49]] - \_Eval[[null[KEYWORD] AS does_not_exist#73]] - \_Eval[[fork2[KEYWORD] AS _fork#49]] - \_Filter[emp_no{f}#52 > 0[INTEGER]] - \_EsRelation[employees][avg_worked_seconds{f}#50, birth_date{f}#51, emp_no{f}#52, first_name{f}#53, gender{f}#54, height{f}#55, height.float{f}#56, height.half_float{f}#57, height.scaled_float{f}#58, hire_date{f}#59, is_rehired{f}#60, job_positions{f}#61, languages{f}#62, languages.byte{f}#63, languages.long{f}#64, languages.short{f}#65, last_name{f}#66, salary{f}#67, salary_change{f}#68, salary_change.int{f}#69, salary_change.keyword{f}#70, salary_change.long{f}#71, still_hired{f}#72] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql deleted file mode 100644 index 1b2a31d2f6afd..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| FORK (WHERE does_not_exist::LONG > 0) - (WHERE emp_no > 0) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected deleted file mode 100644 index 5230e1078a6f8..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected +++ /dev/null @@ -1,14 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, x{r}#24, _fork{r}#25, y{r}#26]] - |_Limit[1000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f()}#27, birth_date{f()}#28, emp_no{f()}#29, first_name{f()}#30, gender{f()}#31, height{f()}#32, height.float{f()}#33, height.half_float{f()}#34, height.scaled_float{f()}#35, hire_date{f()}#36, is_rehired{f()}#37, job_positions{f()}#38, languages{f()}#39, languages.byte{f()}#40, languages.long{f()}#41, languages.short{f()}#42, last_name{f()}#43, salary{f()}#44, salary_change{f()}#45, salary_change.int{f()}#46, salary_change.keyword{f()}#47, salary_change.long{f()}#48, still_hired{f()}#49, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#50, x{r}#51, _fork{r}#52, y{r}#53]] - | \_Eval[[null[INTEGER] AS y#53]] - | \_Eval[[fork1[KEYWORD] AS _fork#52]] - | \_Eval[[TODOUBLE(does_not_exist{f}#50) + 1[INTEGER] AS x#51]] - | \_EsRelation[employees][avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, does_not_exist{f}#50] - \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f()}#54, birth_date{f()}#55, emp_no{f()}#56, first_name{f()}#57, gender{f()}#58, height{f()}#59, height.float{f()}#60, height.half_float{f()}#61, height.scaled_float{f()}#62, hire_date{f()}#63, is_rehired{f()}#64, job_positions{f()}#65, languages{f()}#66, languages.byte{f()}#67, languages.long{f()}#68, languages.short{f()}#69, last_name{f()}#70, salary{f()}#71, salary_change{f()}#72, salary_change.int{f()}#73, salary_change.keyword{f()}#74, salary_change.long{f()}#75, still_hired{f()}#76, does_not_exist{r}#77, x{r}#78, _fork{r}#52, y{r}#79]] - \_Eval[[null[KEYWORD] AS does_not_exist#77, null[DOUBLE] AS x#78]] - \_Eval[[fork2[KEYWORD] AS _fork#52]] - \_Eval[[emp_no{f}#56 + 1[INTEGER] AS y#79]] - \_EsRelation[employees][avg_worked_seconds{f}#54, birth_date{f}#55, emp_no{f}#56, first_name{f}#57, gender{f}#58, height{f}#59, height.float{f}#60, height.half_float{f}#61, height.scaled_float{f}#62, hire_date{f}#63, is_rehired{f}#64, job_positions{f}#65, languages{f}#66, languages.byte{f}#67, languages.long{f}#68, languages.short{f}#69, last_name{f}#70, salary{f}#71, salary_change{f}#72, salary_change.int{f}#73, salary_change.keyword{f}#74, salary_change.long{f}#75, still_hired{f}#76] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql deleted file mode 100644 index f007f2dec96ca..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| FORK (EVAL x = does_not_exist::DOUBLE + 1) - (EVAL y = emp_no + 1) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/analysis.expected deleted file mode 100644 index 466d405f796e8..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/analysis.expected +++ /dev/null @@ -1,19 +0,0 @@ -Limit[10000[INTEGER],false,false] -\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist1{r}#23, does_not_exist2{r}#24, _fork{r}#25, does_not_exist3{r}#26, xyz{r}#27]] - |_Limit[10000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f}#28, birth_date{f}#29, emp_no{f}#30, first_name{f}#31, gender{f}#32, height{f}#33, height.float{f}#34, height.half_float{f}#35, height.scaled_float{f}#36, hire_date{f}#37, is_rehired{f}#38, job_positions{f}#39, languages{f}#40, languages.byte{f}#41, languages.long{f}#42, languages.short{f}#43, last_name{f}#44, salary{f}#45, salary_change{f}#46, salary_change.int{f}#47, salary_change.keyword{f}#48, salary_change.long{f}#49, still_hired{f}#50, does_not_exist1{f}#51, does_not_exist2{f}#52, _fork{r}#53, does_not_exist3{r}#54, xyz{r}#55]] - | \_Eval[[null[KEYWORD] AS does_not_exist3#54, null[KEYWORD] AS xyz#55]] - | \_Eval[[fork1[KEYWORD] AS _fork#53]] - | \_Limit[7[INTEGER],false,false] - | \_OrderBy[[Order[does_not_exist2{f}#52,ASC,LAST]]] - | \_Filter[emp_no{f}#30 > 3[INTEGER]] - | \_Filter[TOLONG(does_not_exist1{f}#51) > 5[INTEGER]] - | \_EsRelation[employees][avg_worked_seconds{f}#28, birth_date{f}#29, emp_no{f}#30, first_name{f}#31, gender{f}#32, height{f}#33, height.float{f}#34, height.half_float{f}#35, height.scaled_float{f}#36, hire_date{f}#37, is_rehired{f}#38, job_positions{f}#39, languages{f}#40, languages.byte{f}#41, languages.long{f}#42, languages.short{f}#43, last_name{f}#44, salary{f}#45, salary_change{f}#46, salary_change.int{f}#47, salary_change.keyword{f}#48, salary_change.long{f}#49, still_hired{f}#50, does_not_exist1{f}#51, does_not_exist2{f}#52] - \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f}#56, birth_date{f}#57, emp_no{f}#58, first_name{f}#59, gender{f}#60, height{f}#61, height.float{f}#62, height.half_float{f}#63, height.scaled_float{f}#64, hire_date{f}#65, is_rehired{f}#66, job_positions{f}#67, languages{f}#68, languages.byte{f}#69, languages.long{f}#70, languages.short{f}#71, last_name{f}#72, salary{f}#73, salary_change{f}#74, salary_change.int{f}#75, salary_change.keyword{f}#76, salary_change.long{f}#77, still_hired{f}#78, does_not_exist1{f}#79, does_not_exist2{r}#80, _fork{r}#53, does_not_exist3{f}#81, xyz{r}#82]] - \_Eval[[null[KEYWORD] AS does_not_exist2#80]] - \_Eval[[fork2[KEYWORD] AS _fork#53]] - \_Eval[[TOSTRING(does_not_exist3{f}#81) AS xyz#82]] - \_Filter[emp_no{f}#58 > 2[INTEGER]] - \_Filter[TOLONG(does_not_exist1{f}#79) > 5[INTEGER]] - \_EsRelation[employees][avg_worked_seconds{f}#56, birth_date{f}#57, emp_no{f}#58, first_name{f}#59, gender{f}#60, height{f}#61, height.float{f}#62, height.half_float{f}#63, height.scaled_float{f}#64, hire_date{f}#65, is_rehired{f}#66, job_positions{f}#67, languages{f}#68, languages.byte{f}#69, languages.long{f}#70, languages.short{f}#71, last_name{f}#72, salary{f}#73, salary_change{f}#74, salary_change.int{f}#75, salary_change.keyword{f}#76, salary_change.long{f}#77, still_hired{f}#78, does_not_exist1{f}#79, does_not_exist3{f}#81] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/query.esql deleted file mode 100644 index 27269779f68d7..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/load/query.esql +++ /dev/null @@ -1,4 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| WHERE does_not_exist1::LONG > 5 -| FORK (WHERE emp_no > 3 | SORT does_not_exist2 | LIMIT 7) - (WHERE emp_no > 2 | EVAL xyz = does_not_exist3::KEYWORD) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/analysis.expected deleted file mode 100644 index 99494fb1c5fff..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/analysis.expected +++ /dev/null @@ -1,21 +0,0 @@ -Limit[10000[INTEGER],false,false] -\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist1{r}#23, does_not_exist2{r}#24, _fork{r}#25, does_not_exist3{r}#26, xyz{r}#27]] - |_Limit[10000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f}#28, birth_date{f}#29, emp_no{f}#30, first_name{f}#31, gender{f}#32, height{f}#33, height.float{f}#34, height.half_float{f}#35, height.scaled_float{f}#36, hire_date{f}#37, is_rehired{f}#38, job_positions{f}#39, languages{f}#40, languages.byte{f}#41, languages.long{f}#42, languages.short{f}#43, last_name{f}#44, salary{f}#45, salary_change{f}#46, salary_change.int{f}#47, salary_change.keyword{f}#48, salary_change.long{f}#49, still_hired{f}#50, does_not_exist1{r}#51, does_not_exist2{r}#52, _fork{r}#53, does_not_exist3{r}#54, xyz{r}#55]] - | \_Eval[[null[NULL] AS does_not_exist3#54, null[KEYWORD] AS xyz#55]] - | \_Eval[[fork1[KEYWORD] AS _fork#53]] - | \_Limit[7[INTEGER],false,false] - | \_OrderBy[[Order[does_not_exist2{r}#52,ASC,LAST]]] - | \_Filter[emp_no{f}#30 > 3[INTEGER]] - | \_Filter[TOLONG(does_not_exist1{r}#51) > 5[INTEGER]] - | \_Eval[[null[NULL] AS does_not_exist1#51, null[NULL] AS does_not_exist2#52]] - | \_EsRelation[employees][avg_worked_seconds{f}#28, birth_date{f}#29, emp_no{f}#30, first_name{f}#31, gender{f}#32, height{f}#33, height.float{f}#34, height.half_float{f}#35, height.scaled_float{f}#36, hire_date{f}#37, is_rehired{f}#38, job_positions{f}#39, languages{f}#40, languages.byte{f}#41, languages.long{f}#42, languages.short{f}#43, last_name{f}#44, salary{f}#45, salary_change{f}#46, salary_change.int{f}#47, salary_change.keyword{f}#48, salary_change.long{f}#49, still_hired{f}#50] - \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f}#56, birth_date{f}#57, emp_no{f}#58, first_name{f}#59, gender{f}#60, height{f}#61, height.float{f}#62, height.half_float{f}#63, height.scaled_float{f}#64, hire_date{f}#65, is_rehired{f}#66, job_positions{f}#67, languages{f}#68, languages.byte{f}#69, languages.long{f}#70, languages.short{f}#71, last_name{f}#72, salary{f}#73, salary_change{f}#74, salary_change.int{f}#75, salary_change.keyword{f}#76, salary_change.long{f}#77, still_hired{f}#78, does_not_exist1{r}#79, does_not_exist2{r}#80, _fork{r}#53, does_not_exist3{r}#81, xyz{r}#82]] - \_Eval[[null[NULL] AS does_not_exist2#80]] - \_Eval[[fork2[KEYWORD] AS _fork#53]] - \_Eval[[TOSTRING(does_not_exist3{r}#81) AS xyz#82]] - \_Filter[emp_no{f}#58 > 2[INTEGER]] - \_Filter[TOLONG(does_not_exist1{r}#79) > 5[INTEGER]] - \_Eval[[null[NULL] AS does_not_exist1#79, null[NULL] AS does_not_exist3#81]] - \_EsRelation[employees][avg_worked_seconds{f}#56, birth_date{f}#57, emp_no{f}#58, first_name{f}#59, gender{f}#60, height{f}#61, height.float{f}#62, height.half_float{f}#63, height.scaled_float{f}#64, hire_date{f}#65, is_rehired{f}#66, job_positions{f}#67, languages{f}#68, languages.byte{f}#69, languages.long{f}#70, languages.short{f}#71, last_name{f}#72, salary{f}#73, salary_change{f}#74, salary_change.int{f}#75, salary_change.keyword{f}#76, salary_change.long{f}#77, still_hired{f}#78] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/query.esql deleted file mode 100644 index c843b72d7d898..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithSort/nullify/query.esql +++ /dev/null @@ -1,4 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| WHERE does_not_exist1::LONG > 5 -| FORK (WHERE emp_no > 3 | SORT does_not_exist2 | LIMIT 7) - (WHERE emp_no > 2 | EVAL xyz = does_not_exist3::KEYWORD) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected deleted file mode 100644 index 3b3a8d51f9ff4..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected +++ /dev/null @@ -1,15 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_OrderBy[[Order[does_not_exist{r}#0,ASC,LAST]]] - \_Fork[[c{r}#1, does_not_exist{r}#0, _fork{r}#2, d{r}#3]] - |_Limit[1000[INTEGER],false,false] - | \_Project[[c{r}#4, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#5, _fork{r}#6, d{r}#7]] - | \_Eval[[null[DOUBLE] AS d#7]] - | \_Eval[[fork1[KEYWORD] AS _fork#6]] - | \_Aggregate[[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#5],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#5]] - | \_EsRelation[employees][avg_worked_seconds{f}#8, birth_date{f}#9, emp_no{f}#10, first_name{f}#11, gender{f}#12, height{f}#13, height.float{f}#14, height.half_float{f}#15, height.scaled_float{f}#16, hire_date{f}#17, is_rehired{f}#18, job_positions{f}#19, languages{f}#20, languages.byte{f}#21, languages.long{f}#22, languages.short{f}#23, last_name{f}#24, salary{f}#25, salary_change{f}#26, salary_change.int{f}#27, salary_change.keyword{f}#28, salary_change.long{f}#29, still_hired{f}#30, does_not_exist{f}#5] - \_Limit[1000[INTEGER],false,false] - \_Project[[c{r}#31, does_not_exist{r}#32, _fork{r}#6, d{r}#33]] - \_Eval[[null[LONG] AS c#31, null[KEYWORD] AS does_not_exist#32]] - \_Eval[[fork2[KEYWORD] AS _fork#6]] - \_Aggregate[[],[AVG(TODOUBLE(salary{f()}#34),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS d#33]] - \_EsRelation[employees][avg_worked_seconds{f}#35, birth_date{f}#36, emp_no{f}#37, first_name{f}#38, gender{f}#39, height{f}#40, height.float{f}#41, height.half_float{f}#42, height.scaled_float{f}#43, hire_date{f}#44, is_rehired{f}#45, job_positions{f}#46, languages{f}#47, languages.byte{f}#48, languages.long{f}#49, languages.short{f}#50, last_name{f}#51, salary{f}#34, salary_change{f}#52, salary_change.int{f}#53, salary_change.keyword{f}#54, salary_change.long{f}#55, still_hired{f}#56] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql deleted file mode 100644 index 3a52496cdfc84..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql +++ /dev/null @@ -1,4 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| FORK (STATS c = COUNT(*) BY does_not_exist) - (STATS d = AVG(salary::DOUBLE)) -| SORT does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected deleted file mode 100644 index 21a0b60c54fbc..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected +++ /dev/null @@ -1,15 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(_fork{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#55]] - \_FuseScoreEval[_score{r}#2,_fork{r}#54,RRF,null] - \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, _fork{r}#54]] - |_Limit[1000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f()}#56, birth_date{f()}#57, emp_no{f()}#58, first_name{f()}#59, gender{f()}#60, height{f()}#61, height.float{f()}#62, height.half_float{f()}#63, height.scaled_float{f()}#64, hire_date{f()}#65, is_rehired{f()}#66, job_positions{f()}#67, languages{f()}#68, languages.byte{f()}#69, languages.long{f()}#70, languages.short{f()}#71, last_name{f()}#72, salary{f()}#73, salary_change{f()}#74, salary_change.int{f()}#75, salary_change.keyword{f()}#76, salary_change.long{f()}#77, still_hired{f()}#78, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#82, _fork{r}#83]] - | \_Eval[[fork1[KEYWORD] AS _fork#83]] - | \_Filter[TOLONG(does_not_exist{f}#82) > 0[INTEGER]] - | \_EsRelation[employees][avg_worked_seconds{f}#56, birth_date{f}#57, emp_no{f}#58, first_name{f}#59, gender{f}#60, height{f}#61, height.float{f}#62, height.half_float{f}#63, height.scaled_float{f}#64, hire_date{f}#65, is_rehired{f}#66, job_positions{f}#67, languages{f}#68, languages.byte{f}#69, languages.long{f}#70, languages.short{f}#71, last_name{f}#72, salary{f}#73, salary_change{f}#74, salary_change.int{f}#75, salary_change.keyword{f}#76, salary_change.long{f}#77, still_hired{f}#78, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{f}#82] - \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f()}#84, birth_date{f()}#85, emp_no{f()}#86, first_name{f()}#87, gender{f()}#88, height{f()}#89, height.float{f()}#90, height.half_float{f()}#91, height.scaled_float{f()}#92, hire_date{f()}#93, is_rehired{f()}#94, job_positions{f()}#95, languages{f()}#96, languages.byte{f()}#97, languages.long{f()}#98, languages.short{f()}#99, last_name{f()}#100, salary{f()}#101, salary_change{f()}#102, salary_change.int{f()}#103, salary_change.keyword{f()}#104, salary_change.long{f()}#105, still_hired{f()}#106, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{r}#107, _fork{r}#83]] - \_Eval[[null[KEYWORD] AS does_not_exist#107]] - \_Eval[[fork2[KEYWORD] AS _fork#83]] - \_Filter[emp_no{f}#86 > 0[INTEGER]] - \_EsRelation[employees][avg_worked_seconds{f}#84, birth_date{f}#85, emp_no{f}#86, first_name{f}#87, gender{f}#88, height{f}#89, height.float{f}#90, height.half_float{f}#91, height.scaled_float{f}#92, hire_date{f}#93, is_rehired{f}#94, job_positions{f}#95, languages{f}#96, languages.byte{f}#97, languages.long{f}#98, languages.short{f}#99, last_name{f}#100, salary{f}#101, salary_change{f}#102, salary_change.int{f}#103, salary_change.keyword{f}#104, salary_change.long{f}#105, still_hired{f}#106, _score{m}#79, _index{m}#80, _id{m}#81] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql deleted file mode 100644 index 2217f682e64de..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql +++ /dev/null @@ -1,4 +0,0 @@ -SET unmapped_fields="load"; FROM employees METADATA _score, _index, _id -| FORK (WHERE does_not_exist::LONG > 0) - (WHERE emp_no > 0) -| FUSE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected deleted file mode 100644 index caa8b7855cbfc..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected +++ /dev/null @@ -1,18 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(x{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS x#55, VALUES(_fork{r}#56,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#57, VALUES(y{r}#58,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#59]] - \_FuseScoreEval[_score{r}#2,_fork{r}#56,LINEAR,null] - \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, x{r}#54, _fork{r}#56, y{r}#58]] - |_Limit[1000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f()}#60, birth_date{f()}#61, emp_no{f()}#62, first_name{f()}#63, gender{f()}#64, height{f()}#65, height.float{f()}#66, height.half_float{f()}#67, height.scaled_float{f()}#68, hire_date{f()}#69, is_rehired{f()}#70, job_positions{f()}#71, languages{f()}#72, languages.byte{f()}#73, languages.long{f()}#74, languages.short{f()}#75, last_name{f()}#76, salary{f()}#77, salary_change{f()}#78, salary_change.int{f()}#79, salary_change.keyword{f()}#80, salary_change.long{f()}#81, still_hired{f()}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#86, x{r}#87, _fork{r}#88, y{r}#89]] - | \_Eval[[null[INTEGER] AS y#89]] - | \_Eval[[fork1[KEYWORD] AS _fork#88]] - | \_Eval[[1[INTEGER] AS x#87]] - | \_Filter[TOLONG(does_not_exist{f}#86) > 0[INTEGER]] - | \_EsRelation[employees][avg_worked_seconds{f}#60, birth_date{f}#61, emp_no{f}#62, first_name{f}#63, gender{f}#64, height{f}#65, height.float{f}#66, height.half_float{f}#67, height.scaled_float{f}#68, hire_date{f}#69, is_rehired{f}#70, job_positions{f}#71, languages{f}#72, languages.byte{f}#73, languages.long{f}#74, languages.short{f}#75, last_name{f}#76, salary{f}#77, salary_change{f}#78, salary_change.int{f}#79, salary_change.keyword{f}#80, salary_change.long{f}#81, still_hired{f}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f}#86] - \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f()}#90, birth_date{f()}#91, emp_no{f()}#92, first_name{f()}#93, gender{f()}#94, height{f()}#95, height.float{f()}#96, height.half_float{f()}#97, height.scaled_float{f()}#98, hire_date{f()}#99, is_rehired{f()}#100, job_positions{f()}#101, languages{f()}#102, languages.byte{f()}#103, languages.long{f()}#104, languages.short{f()}#105, last_name{f()}#106, salary{f()}#107, salary_change{f()}#108, salary_change.int{f()}#109, salary_change.keyword{f()}#110, salary_change.long{f()}#111, still_hired{f()}#112, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#113, x{r}#114, _fork{r}#88, y{r}#115]] - \_Eval[[null[KEYWORD] AS does_not_exist#113, null[INTEGER] AS x#114]] - \_Eval[[fork2[KEYWORD] AS _fork#88]] - \_Eval[[2[INTEGER] AS y#115]] - \_Filter[emp_no{f}#92 > 0[INTEGER]] - \_EsRelation[employees][avg_worked_seconds{f}#90, birth_date{f}#91, emp_no{f}#92, first_name{f}#93, gender{f}#94, height{f}#95, height.float{f}#96, height.half_float{f}#97, height.scaled_float{f}#98, hire_date{f}#99, is_rehired{f}#100, job_positions{f}#101, languages{f}#102, languages.byte{f}#103, languages.long{f}#104, languages.short{f}#105, last_name{f}#106, salary{f}#107, salary_change{f}#108, salary_change.int{f}#109, salary_change.keyword{f}#110, salary_change.long{f}#111, still_hired{f}#112, _score{m}#83, _index{m}#84, _id{m}#85] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql deleted file mode 100644 index 6ca46384903c8..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql +++ /dev/null @@ -1,4 +0,0 @@ -SET unmapped_fields="load"; FROM employees METADATA _score, _index, _id -| FORK (WHERE does_not_exist::LONG > 0 | EVAL x = 1) - (WHERE emp_no > 0 | EVAL y = 2) -| FUSE LINEAR diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected deleted file mode 100644 index 8a3d0ec4a83d7..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected +++ /dev/null @@ -1,16 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(x{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS x#55, VALUES(_fork{r}#56,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#57, VALUES(y{r}#58,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#59]] - \_FuseScoreEval[_score{r}#2,_fork{r}#56,RRF,null] - \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, x{r}#54, _fork{r}#56, y{r}#58]] - |_Limit[1000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f()}#60, birth_date{f()}#61, emp_no{f()}#62, first_name{f()}#63, gender{f()}#64, height{f()}#65, height.float{f()}#66, height.half_float{f()}#67, height.scaled_float{f()}#68, hire_date{f()}#69, is_rehired{f()}#70, job_positions{f()}#71, languages{f()}#72, languages.byte{f()}#73, languages.long{f()}#74, languages.short{f()}#75, last_name{f()}#76, salary{f()}#77, salary_change{f()}#78, salary_change.int{f()}#79, salary_change.keyword{f()}#80, salary_change.long{f()}#81, still_hired{f()}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#86, x{r}#87, _fork{r}#88, y{r}#89]] - | \_Eval[[null[INTEGER] AS y#89]] - | \_Eval[[fork1[KEYWORD] AS _fork#88]] - | \_Eval[[TODOUBLE(does_not_exist{f}#86) + 1[INTEGER] AS x#87]] - | \_EsRelation[employees][avg_worked_seconds{f}#60, birth_date{f}#61, emp_no{f}#62, first_name{f}#63, gender{f}#64, height{f}#65, height.float{f}#66, height.half_float{f}#67, height.scaled_float{f}#68, hire_date{f}#69, is_rehired{f}#70, job_positions{f}#71, languages{f}#72, languages.byte{f}#73, languages.long{f}#74, languages.short{f}#75, last_name{f}#76, salary{f}#77, salary_change{f}#78, salary_change.int{f}#79, salary_change.keyword{f}#80, salary_change.long{f}#81, still_hired{f}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f}#86] - \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f()}#90, birth_date{f()}#91, emp_no{f()}#92, first_name{f()}#93, gender{f()}#94, height{f()}#95, height.float{f()}#96, height.half_float{f()}#97, height.scaled_float{f()}#98, hire_date{f()}#99, is_rehired{f()}#100, job_positions{f()}#101, languages{f()}#102, languages.byte{f()}#103, languages.long{f()}#104, languages.short{f()}#105, last_name{f()}#106, salary{f()}#107, salary_change{f()}#108, salary_change.int{f()}#109, salary_change.keyword{f()}#110, salary_change.long{f()}#111, still_hired{f()}#112, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#113, x{r}#114, _fork{r}#88, y{r}#115]] - \_Eval[[null[KEYWORD] AS does_not_exist#113, null[DOUBLE] AS x#114]] - \_Eval[[fork2[KEYWORD] AS _fork#88]] - \_Eval[[emp_no{f}#92 + 1[INTEGER] AS y#115]] - \_EsRelation[employees][avg_worked_seconds{f}#90, birth_date{f}#91, emp_no{f}#92, first_name{f}#93, gender{f}#94, height{f}#95, height.float{f}#96, height.half_float{f}#97, height.scaled_float{f}#98, hire_date{f}#99, is_rehired{f}#100, job_positions{f}#101, languages{f}#102, languages.byte{f}#103, languages.long{f}#104, languages.short{f}#105, last_name{f}#106, salary{f}#107, salary_change{f}#108, salary_change.int{f}#109, salary_change.keyword{f}#110, salary_change.long{f}#111, still_hired{f}#112, _score{m}#83, _index{m}#84, _id{m}#85] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql deleted file mode 100644 index 28caa1c3f1e98..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql +++ /dev/null @@ -1,4 +0,0 @@ -SET unmapped_fields="load"; FROM employees METADATA _score, _index, _id -| FORK (EVAL x = does_not_exist::DOUBLE + 1) - (EVAL y = emp_no + 1) -| FUSE RRF diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected deleted file mode 100644 index 01fc4148688e2..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[42[INTEGER] AS does_not_exist_field#0]] - \_Project[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#1]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/query.esql deleted file mode 100644 index 945f0e290ca38..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| KEEP does_not_exist_field -| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected deleted file mode 100644 index f95ae9f74e6dc..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[42[INTEGER] AS does_not_exist_field#0]] - \_Project[[does_not_exist_field{r}#1]] - \_Eval[[null[NULL] AS does_not_exist_field#1]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql deleted file mode 100644 index 4337b35ba4b2e..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| KEEP does_not_exist_field -| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected deleted file mode 100644 index 3532a4c9c1d48..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_LookupJoin[LEFT,[language_code{r}#0],[language_code{f()}#1],false,null] - |_Eval[[TOINTEGER(does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2) AS language_code#0]] - | \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#2] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}#1, language_name{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql deleted file mode 100644 index 45bedb56b16b8..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| EVAL language_code = does_not_exist :: INTEGER -| LOOKUP JOIN languages_lookup ON language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/analysis.expected deleted file mode 100644 index 3feb294dd5dc4..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/analysis.expected +++ /dev/null @@ -1,6 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[TODOUBLE(does_not_exist{f}#0) + 1[INTEGER] AS x#1]] - \_LookupJoin[LEFT,[language_code{r}#2],[language_code{f}#3],false,null] - |_Eval[[languages{f}#4 AS language_code#2]] - | \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#7, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#4, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26, does_not_exist{f}#0] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}#3, language_name{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/query.esql deleted file mode 100644 index 787070f352209..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/load/query.esql +++ /dev/null @@ -1,4 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| EVAL language_code = languages -| LOOKUP JOIN languages_lookup ON language_code -| EVAL x = does_not_exist::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/analysis.expected deleted file mode 100644 index de08464ba34a8..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/analysis.expected +++ /dev/null @@ -1,7 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[TODOUBLE(does_not_exist{r}#0) + 1[INTEGER] AS x#1]] - \_LookupJoin[LEFT,[language_code{r}#2],[language_code{f}#3],false,null] - |_Eval[[languages{f}#4 AS language_code#2, null[NULL] AS does_not_exist#5]] - | \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#8, first_name{f}#9, gender{f}#10, height{f}#11, height.float{f}#12, height.half_float{f}#13, height.scaled_float{f}#14, hire_date{f}#15, is_rehired{f}#16, job_positions{f}#17, languages{f}#4, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27] - \_Eval[[null[NULL] AS does_not_exist#0]] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}#3, language_name{f}#28] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/query.esql deleted file mode 100644 index ba5f12db31aa2..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithEval/nullify/query.esql +++ /dev/null @@ -1,4 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| EVAL language_code = languages -| LOOKUP JOIN languages_lookup ON language_code -| EVAL x = does_not_exist::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected deleted file mode 100644 index e3fe21e3dfcb0..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected +++ /dev/null @@ -1,6 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Filter[TOLONG(does_not_exist{f}#0) > 0[INTEGER]] - \_LookupJoin[LEFT,[language_code{r}#1],[language_code{f()}#2],false,null] - |_Eval[[languages{f()}#3 AS language_code#1]] - | \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#3, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#0] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}#2, language_name{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql deleted file mode 100644 index face9633033a7..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql +++ /dev/null @@ -1,4 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| EVAL language_code = languages -| LOOKUP JOIN languages_lookup ON language_code -| WHERE does_not_exist::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/analysis.expected deleted file mode 100644 index e40fa24e6653b..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[event_duration{r}#0]] - \_Eval[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#1 AS event_duration#0]] - \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#5, $$event_duration$converted_to$double{f$}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/local_physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/local_physical_optimization.expected deleted file mode 100644 index 51d725ac13932..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/local_physical_optimization.expected +++ /dev/null @@ -1,6 +0,0 @@ -ProjectExec[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#0 AS event_duration#1]] -\_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#0],false] - \_ProjectExec[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#0]] - \_FieldExtractExec[$$event_duration$converted_to$double{f$}#0]<[],[]> - \_EsQueryExec[sample_data,no_mapping_sample_data], indexMode[standard], [_doc{f}#2], limit[1000], sort[] estimatedRowSize[12] queryBuilderAndTags [[QueryBuilderAndTags[query=null, tags=[]]]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/logical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/logical_optimization.expected deleted file mode 100644 index 162b4ec77ad2a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/logical_optimization.expected +++ /dev/null @@ -1,3 +0,0 @@ -Project[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#0 AS event_duration#1]] -\_Limit[1000[INTEGER],false,false] - \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#5, $$event_duration$converted_to$double{f$}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/physical_optimization.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/physical_optimization.expected deleted file mode 100644 index 49d35b4a9b75b..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/physical_optimization.expected +++ /dev/null @@ -1,7 +0,0 @@ -ProjectExec[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#0 AS event_duration#1]] -\_LimitExec[1000[INTEGER],null] - \_ExchangeExec[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#0],false] - \_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<> -Project[[$$event_duration$converted_to$double{f(MultiTypeEsField)$}#0]] -\_Limit[1000[INTEGER],false,false] - \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#5, $$event_duration$converted_to$double{f$}#0]<>]] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql deleted file mode 100644 index 4d67c32286e58..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM sample_data, no_mapping_sample_data -| EVAL event_duration = event_duration :: DOUBLE -| KEEP event_duration diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/analysis.expected deleted file mode 100644 index bfa31bd940d18..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[TODOUBLE(event_duration{f(EsField)}#0) AS x#1]] - \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#0, message{f}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/query.esql deleted file mode 100644 index 59b35e88e844b..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testMappedToNonKeywordInOneIndexOnlyCast/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM sample_data, no_mapping_sample_data -| EVAL x = event_duration :: DOUBLE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected deleted file mode 100644 index 056d8546be64a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[@timestamp{f(DateEsField)}#0, x{r}#1, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2]] - \_Eval[[COALESCE(unmapped_message{f(PotentiallyUnmappedKeywordEsField)}#3,missing[KEYWORD]) AS x#1]] - \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6, unmapped_message{f}#3, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/query.esql deleted file mode 100644 index 578e1fcb86bb8..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM sample_data, partial_mapping_sample_data -| EVAL x = COALESCE(unmapped_message, "missing") -| KEEP @timestamp, x, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected deleted file mode 100644 index e32df7a3a8f8d..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[@timestamp{f(DateEsField)}#0, x{r}#1, does_not_exist{r}#2]] - \_Eval[[COALESCE(unmapped_message{r}#3,missing[KEYWORD]) AS x#1]] - \_Eval[[null[NULL] AS unmapped_message#3, null[NULL] AS does_not_exist#2]] - \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/query.esql deleted file mode 100644 index 8a34446c7a5cc..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithEval/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; FROM sample_data, partial_mapping_sample_data -| EVAL x = COALESCE(unmapped_message, "missing") -| KEEP @timestamp, x, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/analysis.expected deleted file mode 100644 index a3725a08f77a4..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[unmapped_message{f(PotentiallyUnmappedKeywordEsField)}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#1, unmapped_message{f(PotentiallyUnmappedKeywordEsField)}#0]] - \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#5, unmapped_message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/query.esql deleted file mode 100644 index 870af673da1a0..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM sample_data, partial_mapping_sample_data -| STATS c = COUNT(*) BY unmapped_message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/analysis.expected deleted file mode 100644 index e1f96c50471b1..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[unmapped_message{r}#0],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#1, unmapped_message{r}#0]] - \_Eval[[null[NULL] AS unmapped_message#0]] - \_EsRelation[sample_data,partial_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#5] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/query.esql deleted file mode 100644 index d44b1ad301021..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testPartiallyMappedFieldWithStats/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM sample_data, partial_mapping_sample_data -| STATS c = COUNT(*) BY unmapped_message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected deleted file mode 100644 index f239763e796e7..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[TODOUBLE(does_not_exist{f}#0) + 1[INTEGER] AS x#1]] - \_Project[[avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4 AS employee_number#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#0]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/query.esql deleted file mode 100644 index 15a3d0131d523..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| RENAME emp_no AS employee_number -| EVAL x = does_not_exist::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected deleted file mode 100644 index f96459400cd9a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[TODOUBLE(does_not_exist{r}#0) + 1[INTEGER] AS x#1]] - \_Project[[avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4 AS employee_number#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{r}#0]] - \_Eval[[null[NULL] AS does_not_exist#0]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql deleted file mode 100644 index 7475a95153a3a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| RENAME emp_no AS employee_number -| EVAL x = does_not_exist::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected deleted file mode 100644 index 41a803dee2b34..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2 AS employee_number#3, first_name{f(KeywordEsField)}#4, gender{f(KeywordEsField)}#5, height{f(EsField)}#6, height.float{f(EsField)}#7, height.half_float{f(EsField)}#8, height.scaled_float{f(EsField)}#9, hire_date{f(DateEsField)}#10, is_rehired{f(EsField)}#11, job_positions{f(KeywordEsField)}#12, languages{f(EsField)}#13, languages.byte{f(EsField)}#14, languages.long{f(EsField)}#15, languages.short{f(EsField)}#16, last_name{f(KeywordEsField)}#17, salary{f(EsField)}#18, salary_change{f(EsField)}#19, salary_change.int{f(EsField)}#20, salary_change.keyword{f(KeywordEsField)}#21, salary_change.long{f(EsField)}#22, still_hired{f(EsField)}#23, neither_does_this{f(PotentiallyUnmappedKeywordEsField)}#24 AS now_it_does#25]] - \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#26, neither_does_this{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/query.esql deleted file mode 100644 index efad9ee315214..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| RENAME does_not_exist_field AS now_it_does, neither_does_this AS now_it_does, emp_no AS employee_number diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected deleted file mode 100644 index f828b3f7c9f30..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[avg_worked_seconds{f(EsField)}#0, birth_date{f(DateEsField)}#1, emp_no{f(EsField)}#2 AS employee_number#3, first_name{f(KeywordEsField)}#4, gender{f(KeywordEsField)}#5, height{f(EsField)}#6, height.float{f(EsField)}#7, height.half_float{f(EsField)}#8, height.scaled_float{f(EsField)}#9, hire_date{f(DateEsField)}#10, is_rehired{f(EsField)}#11, job_positions{f(KeywordEsField)}#12, languages{f(EsField)}#13, languages.byte{f(EsField)}#14, languages.long{f(EsField)}#15, languages.short{f(EsField)}#16, last_name{f(KeywordEsField)}#17, salary{f(EsField)}#18, salary_change{f(EsField)}#19, salary_change.int{f(EsField)}#20, salary_change.keyword{f(KeywordEsField)}#21, salary_change.long{f(EsField)}#22, still_hired{f(EsField)}#23, neither_does_this{r}#24 AS now_it_does#25]] - \_Eval[[null[NULL] AS does_not_exist_field#26, null[NULL] AS neither_does_this#24]] - \_EsRelation[employees][avg_worked_seconds{f}#0, birth_date{f}#1, emp_no{f}#2, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/query.esql deleted file mode 100644 index db1febeb315ad..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameRepeated/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| RENAME does_not_exist_field AS now_it_does, neither_does_this AS now_it_does, emp_no AS employee_number diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRow/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRow/load/query.esql deleted file mode 100644 index a37a2ef472baa..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRow/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; ROW x = 1 -| EVAL y = does_not_exist_field1::INTEGER + x -| KEEP *, does_not_exist_field2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected deleted file mode 100644 index b6e10e3bc15c1..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_OrderBy[[Order[TOLONG(does_not_exist1{f}#0) + 1[INTEGER],ASC,LAST], Order[does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#1,DESC,FIRST], Order[emp_no{f(EsField)}#2,ASC,LAST]]] - \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist1{f}#0, does_not_exist2{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/query.esql deleted file mode 100644 index df129647e7c8a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| SORT does_not_exist1::LONG + 1, does_not_exist2 DESC, emp_no ASC diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected deleted file mode 100644 index 272402c1c32eb..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_OrderBy[[Order[TOLONG(does_not_exist1{r}#0) + 1[INTEGER],ASC,LAST], Order[does_not_exist2{r}#1,DESC,FIRST], Order[emp_no{f(EsField)}#2,ASC,LAST]]] - \_Eval[[null[NULL] AS does_not_exist1#0, null[NULL] AS does_not_exist2#1]] - \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#2, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/query.esql deleted file mode 100644 index 7b1dadb3f7ed2..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSortMultiple/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| SORT does_not_exist1::LONG + 1, does_not_exist2 DESC, emp_no ASC diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/analysis.expected deleted file mode 100644 index 97a29a5f794e0..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{f}#0) > 0[INTEGER]] AS c#1]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/query.esql deleted file mode 100644 index c761b990a28aa..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/analysis.expected deleted file mode 100644 index 31ed40e729ba7..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{r}#0) > 0[INTEGER]] AS c#1]] - \_Eval[[null[NULL] AS does_not_exist1#0]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/query.esql deleted file mode 100644 index 7c028cc985242..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected deleted file mode 100644 index 72036927b0717..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0],[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0]] - \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/query.esql deleted file mode 100644 index d13f24be60435..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| STATS BY does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/analysis.expected deleted file mode 100644 index dc5330d4bd4ae..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[does_not_exist_field{r}#0],[does_not_exist_field{r}#0]] - \_Eval[[null[NULL] AS does_not_exist_field#0]] - \_EsRelation[employees][avg_worked_seconds{f}#1, birth_date{f}#2, emp_no{f}#3, first_name{f}#4, gender{f}#5, height{f}#6, height.float{f}#7, height.half_float{f}#8, height.scaled_float{f}#9, hire_date{f}#10, is_rehired{f}#11, job_positions{f}#12, languages{f}#13, languages.byte{f}#14, languages.long{f}#15, languages.short{f}#16, last_name{f}#17, salary{f}#18, salary_change{f}#19, salary_change.int{f}#20, salary_change.keyword{f}#21, salary_change.long{f}#22, still_hired{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/query.esql deleted file mode 100644 index b4ef8dbc01160..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsBy/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| STATS BY does_not_exist_field diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected deleted file mode 100644 index 4266a433ba529..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[],[COUNT(does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt#1]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/query.esql deleted file mode 100644 index 2e1086f20474e..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| STATS cnt = COUNT(does_not_exist_field) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/analysis.expected deleted file mode 100644 index bce83c7e94ff2..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[],[COUNT(does_not_exist_field{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS cnt#1]] - \_Eval[[null[NULL] AS does_not_exist_field#0]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/query.esql deleted file mode 100644 index e8fb3888650cf..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCount/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| STATS cnt = COUNT(does_not_exist_field) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/analysis.expected deleted file mode 100644 index 0e4402c48cdba..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{f}#0) > 0[INTEGER]] AS c#1]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist1{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/query.esql deleted file mode 100644 index c761b990a28aa..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/analysis.expected deleted file mode 100644 index 31ed40e729ba7..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{r}#0) > 0[INTEGER]] AS c#1]] - \_Eval[[null[NULL] AS does_not_exist1#0]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/query.esql deleted file mode 100644 index 7c028cc985242..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsCountWhere/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected deleted file mode 100644 index 20e247409cc03..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0, emp_no{f(EsField)}#1],[SUM(TODOUBLE(does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0, emp_no{f(EsField)}#1]] - \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#1, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26, does_not_exist2{f}#0, does_not_exist1{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/query.esql deleted file mode 100644 index ecc9a01cd10d1..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected deleted file mode 100644 index 4e82f82142c41..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[does_not_exist2{r}#0, emp_no{f(EsField)}#1],[SUM(TODOUBLE(does_not_exist1{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist2{r}#0, emp_no{f(EsField)}#1]] - \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist1#2]] - \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#1, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/query.esql deleted file mode 100644 index 6887849dbdcd4..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultiple/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| STATS s = SUM(does_not_exist1::DOUBLE), c = COUNT(*) BY does_not_exist2, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected deleted file mode 100644 index de76cbb9a017a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{f}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER] OR TOLONG(does_not_exist2{f}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{f(PotentiallyUnmappedKeywordEsField)}#4)] AS c2#5]] - \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#1, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27, does_not_exist1{f}#0, does_not_exist2{f}#2, does_not_exist3{f}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/query.esql deleted file mode 100644 index 3078319477f7f..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| STATS c1 = COUNT(*) WHERE does_not_exist1::LONG > 0 OR emp_no > 0 OR does_not_exist2::LONG < 100, - c2 = COUNT(*) WHERE does_not_exist3 IS NULL diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected deleted file mode 100644 index 6f8fec253f83b..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{r}#0) > 0[INTEGER] OR emp_no{f}#1 > 0[INTEGER] OR TOLONG(does_not_exist2{r}#2) < 100[INTEGER]] AS c1#3, FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),ISNULL(does_not_exist3{r}#4)] AS c2#5]] - \_Eval[[null[NULL] AS does_not_exist1#0, null[NULL] AS does_not_exist2#2, null[NULL] AS does_not_exist3#4]] - \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#1, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/query.esql deleted file mode 100644 index 6f052b1a79cb2..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsMultipleCountWhere/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| STATS c1 = COUNT(*) WHERE does_not_exist1::LONG > 0 OR emp_no > 0 OR does_not_exist2::LONG < 100, - c2 = COUNT(*) WHERE does_not_exist3 IS NULL diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected deleted file mode 100644 index 3da6706296c63..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0],[SUM(TODOUBLE(does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#1),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#2, does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0]] - \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist2{f}#0, does_not_exist1{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/query.esql deleted file mode 100644 index 4b45cf86d8cb5..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/analysis.expected deleted file mode 100644 index 75f108928c116..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[does_not_exist2{r}#0],[SUM(TODOUBLE(does_not_exist1{r}#1),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#2, does_not_exist2{r}#0]] - \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist1#1]] - \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/query.esql deleted file mode 100644 index 29d53f6beba5b..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumBy/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected deleted file mode 100644 index f8c89887de2f8..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[TODOUBLE(does_not_exist2{f}#0) + TODOUBLE(does_not_exist3{f}#1) AS s0#2, emp_no{f(EsField)}#3 AS s1#4],[SUM(TODOUBLE(does_not_exist1{f}#5),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + s0{r}#2 + s1{r}#4 AS sum#6, s0{r}#2, s1{r}#4]] - \_EsRelation[employees][avg_worked_seconds{f}#7, birth_date{f}#8, emp_no{f}#3, first_name{f}#9, gender{f}#10, height{f}#11, height.float{f}#12, height.half_float{f}#13, height.scaled_float{f}#14, hire_date{f}#15, is_rehired{f}#16, job_positions{f}#17, languages{f}#18, languages.byte{f}#19, languages.long{f}#20, languages.short{f}#21, last_name{f}#22, salary{f}#23, salary_change{f}#24, salary_change.int{f}#25, salary_change.keyword{f}#26, salary_change.long{f}#27, still_hired{f}#28, does_not_exist2{f}#0, does_not_exist3{f}#1, does_not_exist1{f}#5, s0{f}#29] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/query.esql deleted file mode 100644 index c8ed9b159cb2a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| STATS sum = SUM(does_not_exist1::DOUBLE) + s0 + s1 BY s0 = does_not_exist2::DOUBLE + does_not_exist3::DOUBLE, s1 = emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected deleted file mode 100644 index f324c6cc494bb..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[TODOUBLE(does_not_exist2{r}#0) + TODOUBLE(does_not_exist3{r}#1) AS s0#2, emp_no{f(EsField)}#3 AS s1#4],[SUM(TODOUBLE(does_not_exist1{r}#5),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + s0{r}#2 + s1{r}#4 AS sum#6, s0{r}#2, s1{r}#4]] - \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist3#1, null[NULL] AS does_not_exist1#5, null[NULL] AS s0#7]] - \_EsRelation[employees][avg_worked_seconds{f}#8, birth_date{f}#9, emp_no{f}#3, first_name{f}#10, gender{f}#11, height{f}#12, height.float{f}#13, height.half_float{f}#14, height.scaled_float{f}#15, hire_date{f}#16, is_rehired{f}#17, job_positions{f}#18, languages{f}#19, languages.byte{f}#20, languages.long{f}#21, languages.short{f}#22, last_name{f}#23, salary{f}#24, salary_change{f}#25, salary_change.int{f}#26, salary_change.keyword{f}#27, salary_change.long{f}#28, still_hired{f}#29] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/query.esql deleted file mode 100644 index d4152fb7a5e2f..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByComplex/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| STATS sum = SUM(does_not_exist1::DOUBLE) + s0 + s1 BY s0 = does_not_exist2::DOUBLE + does_not_exist3::DOUBLE, s1 = emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected deleted file mode 100644 index 441d733d2e22d..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[TODOUBLE(does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0) AS d2#1, emp_no{f(EsField)}#2],[SUM(TODOUBLE(does_not_exist1{f}#3),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + d2{r}#1 AS s#4, d2{r}#1, emp_no{f(EsField)}#2]] - \_EsRelation[employees][avg_worked_seconds{f}#5, birth_date{f}#6, emp_no{f}#2, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#16, languages.byte{f}#17, languages.long{f}#18, languages.short{f}#19, last_name{f}#20, salary{f}#21, salary_change{f}#22, salary_change.int{f}#23, salary_change.keyword{f}#24, salary_change.long{f}#25, still_hired{f}#26, does_not_exist2{f}#0, does_not_exist1{f}#3, d2{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/query.esql deleted file mode 100644 index d548e72eda5de..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| STATS s = SUM(does_not_exist1::DOUBLE) + d2 BY d2 = does_not_exist2::DOUBLE, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected deleted file mode 100644 index bcfbad0e4899c..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[TODOUBLE(does_not_exist2{r}#0) AS d2#1, emp_no{f(EsField)}#2],[SUM(TODOUBLE(does_not_exist1{r}#3),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) + d2{r}#1 AS s#4, d2{r}#1, emp_no{f(EsField)}#2]] - \_Eval[[null[NULL] AS does_not_exist2#0, null[NULL] AS does_not_exist1#3, null[NULL] AS d2#5]] - \_EsRelation[employees][avg_worked_seconds{f}#6, birth_date{f}#7, emp_no{f}#2, first_name{f}#8, gender{f}#9, height{f}#10, height.float{f}#11, height.half_float{f}#12, height.scaled_float{f}#13, hire_date{f}#14, is_rehired{f}#15, job_positions{f}#16, languages{f}#17, languages.byte{f}#18, languages.long{f}#19, languages.short{f}#20, last_name{f}#21, salary{f}#22, salary_change{f}#23, salary_change.int{f}#24, salary_change.keyword{f}#25, salary_change.long{f}#26, still_hired{f}#27] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/query.esql deleted file mode 100644 index c9f8f55bbee50..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsSumByMultiple/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| STATS s = SUM(does_not_exist1::DOUBLE) + d2 BY d2 = does_not_exist2::DOUBLE, emp_no diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/analysis.expected deleted file mode 100644 index 190b386040c51..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/analysis.expected +++ /dev/null @@ -1,11 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[emp_no{r}#0, language_code{r}#1]] - \_UnionAll[[avg_worked_seconds{r}#2, birth_date{r}#3, emp_no{r}#0, first_name{r}#4, gender{r}#5, height{r}#6, height.float{r}#7, height.half_float{r}#8, height.scaled_float{r}#9, hire_date{r}#10, is_rehired{r}#11, job_positions{r}#12, languages{r}#13, languages.byte{r}#14, languages.long{r}#15, languages.short{r}#16, last_name{r}#17, salary{r}#18, salary_change{r}#19, salary_change.int{r}#20, salary_change.keyword{r}#21, salary_change.long{r}#22, still_hired{r}#23, language_code{r}#1, language_name{r}#24, does_not_exist{r}#25]] - |_Project[[avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48, language_code{r}#49, language_name{r}#50, does_not_exist{r}#51]] - | \_Eval[[null[INTEGER] AS language_code#49, null[KEYWORD] AS language_name#50, null[KEYWORD] AS does_not_exist#51]] - | \_EsRelation[employees][avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48] - \_Project[[avg_worked_seconds{r}#52, birth_date{r}#53, emp_no{r}#54, first_name{r}#55, gender{r}#56, height{r}#57, height.float{r}#58, height.half_float{r}#59, height.scaled_float{r}#60, hire_date{r}#61, is_rehired{r}#62, job_positions{r}#63, languages{r}#64, languages.byte{r}#65, languages.long{r}#66, languages.short{r}#67, last_name{r}#68, salary{r}#69, salary_change{r}#70, salary_change.int{r}#71, salary_change.keyword{r}#72, salary_change.long{r}#73, still_hired{r}#74, language_code{f}#75, language_name{f}#76, does_not_exist{f}#77]] - \_Eval[[null[LONG] AS avg_worked_seconds#52, null[DATETIME] AS birth_date#53, null[INTEGER] AS emp_no#54, null[KEYWORD] AS first_name#55, null[KEYWORD] AS gender#56, null[DOUBLE] AS height#57, null[DOUBLE] AS height.float#58, null[DOUBLE] AS height.half_float#59, null[DOUBLE] AS height.scaled_float#60, null[DATETIME] AS hire_date#61, null[BOOLEAN] AS is_rehired#62, null[KEYWORD] AS job_positions#63, null[INTEGER] AS languages#64, null[INTEGER] AS languages.byte#65, null[LONG] AS languages.long#66, null[INTEGER] AS languages.short#67, null[KEYWORD] AS last_name#68, null[INTEGER] AS salary#69, null[DOUBLE] AS salary_change#70, null[INTEGER] AS salary_change.int#71, null[KEYWORD] AS salary_change.keyword#72, null[LONG] AS salary_change.long#73, null[BOOLEAN] AS still_hired#74]] - \_Subquery[] - \_Filter[TOLONG(does_not_exist{f}#77) > 0[INTEGER]] - \_EsRelation[languages][language_code{f}#75, language_name{f}#76, does_not_exist{f}#77] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/query.esql deleted file mode 100644 index f6110cf298e18..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees, (FROM languages | WHERE does_not_exist::LONG > 0) -| KEEP emp_no, language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/analysis.expected deleted file mode 100644 index 755aed8c8303b..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/analysis.expected +++ /dev/null @@ -1,12 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[emp_no{r}#0, language_code{r}#1]] - \_UnionAll[[avg_worked_seconds{r}#2, birth_date{r}#3, emp_no{r}#0, first_name{r}#4, gender{r}#5, height{r}#6, height.float{r}#7, height.half_float{r}#8, height.scaled_float{r}#9, hire_date{r}#10, is_rehired{r}#11, job_positions{r}#12, languages{r}#13, languages.byte{r}#14, languages.long{r}#15, languages.short{r}#16, last_name{r}#17, salary{r}#18, salary_change{r}#19, salary_change.int{r}#20, salary_change.keyword{r}#21, salary_change.long{r}#22, still_hired{r}#23, language_code{r}#1, language_name{r}#24, does_not_exist{r}#25]] - |_Project[[avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48, language_code{r}#49, language_name{r}#50, does_not_exist{r}#51]] - | \_Eval[[null[INTEGER] AS language_code#49, null[KEYWORD] AS language_name#50, null[NULL] AS does_not_exist#51]] - | \_EsRelation[employees][avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48] - \_Project[[avg_worked_seconds{r}#52, birth_date{r}#53, emp_no{r}#54, first_name{r}#55, gender{r}#56, height{r}#57, height.float{r}#58, height.half_float{r}#59, height.scaled_float{r}#60, hire_date{r}#61, is_rehired{r}#62, job_positions{r}#63, languages{r}#64, languages.byte{r}#65, languages.long{r}#66, languages.short{r}#67, last_name{r}#68, salary{r}#69, salary_change{r}#70, salary_change.int{r}#71, salary_change.keyword{r}#72, salary_change.long{r}#73, still_hired{r}#74, language_code{f}#75, language_name{f}#76, does_not_exist{r}#77]] - \_Eval[[null[LONG] AS avg_worked_seconds#52, null[DATETIME] AS birth_date#53, null[INTEGER] AS emp_no#54, null[KEYWORD] AS first_name#55, null[KEYWORD] AS gender#56, null[DOUBLE] AS height#57, null[DOUBLE] AS height.float#58, null[DOUBLE] AS height.half_float#59, null[DOUBLE] AS height.scaled_float#60, null[DATETIME] AS hire_date#61, null[BOOLEAN] AS is_rehired#62, null[KEYWORD] AS job_positions#63, null[INTEGER] AS languages#64, null[INTEGER] AS languages.byte#65, null[LONG] AS languages.long#66, null[INTEGER] AS languages.short#67, null[KEYWORD] AS last_name#68, null[INTEGER] AS salary#69, null[DOUBLE] AS salary_change#70, null[INTEGER] AS salary_change.int#71, null[KEYWORD] AS salary_change.keyword#72, null[LONG] AS salary_change.long#73, null[BOOLEAN] AS still_hired#74]] - \_Subquery[] - \_Filter[TOLONG(does_not_exist{r}#77) > 0[INTEGER]] - \_Eval[[null[NULL] AS does_not_exist#77]] - \_EsRelation[languages][language_code{f}#75, language_name{f}#76] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/query.esql deleted file mode 100644 index 6bd3350834a49..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquery/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees, (FROM languages | WHERE does_not_exist::LONG > 0) -| KEEP emp_no, language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/load/query.esql deleted file mode 100644 index 7c1e28505d1fa..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; SET unmapped_fields="load"; FROM employees, (FROM languages | KEEP emp_no) -| KEEP emp_no, language_code -| WHERE emp_no > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/nullify/query.esql deleted file mode 100644 index 62dc68de394b6..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeep/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; SET unmapped_fields="load"; FROM employees, (FROM languages | KEEP emp_no) -| KEEP emp_no, language_code -| WHERE emp_no > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected deleted file mode 100644 index 50d5fdfd9af0d..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected +++ /dev/null @@ -1,11 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[emp_no{r}#0, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] - \_UnionAll[[avg_worked_seconds{r}#4, birth_date{r}#5, emp_no{r}#0, first_name{r}#6, gender{r}#7, height{r}#8, height.float{r}#9, height.half_float{r}#10, height.scaled_float{r}#11, hire_date{r}#12, is_rehired{r}#13, job_positions{r}#14, languages{r}#15, languages.byte{r}#16, languages.long{r}#17, languages.short{r}#18, last_name{r}#19, salary{r}#20, salary_change{r}#21, salary_change.int{r}#22, salary_change.keyword{r}#23, salary_change.long{r}#24, still_hired{r}#25, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] - |_Project[[avg_worked_seconds{f()}#26, birth_date{f()}#27, emp_no{f()}#28, first_name{f()}#29, gender{f()}#30, height{f()}#31, height.float{f()}#32, height.half_float{f()}#33, height.scaled_float{f()}#34, hire_date{f()}#35, is_rehired{f()}#36, job_positions{f()}#37, languages{f()}#38, languages.byte{f()}#39, languages.long{f()}#40, languages.short{f()}#41, last_name{f()}#42, salary{f()}#43, salary_change{f()}#44, salary_change.int{f()}#45, salary_change.keyword{f()}#46, salary_change.long{f()}#47, still_hired{f()}#48, language_code{r}#49, unmapped1{r}#50, unmapped2{r}#51]] - | \_Eval[[null[INTEGER] AS language_code#49, null[KEYWORD] AS unmapped1#50, null[KEYWORD] AS unmapped2#51]] - | \_EsRelation[employees][avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48] - \_Project[[avg_worked_seconds{r}#52, birth_date{r}#53, emp_no{r}#54, first_name{r}#55, gender{r}#56, height{r}#57, height.float{r}#58, height.half_float{r}#59, height.scaled_float{r}#60, hire_date{r}#61, is_rehired{r}#62, job_positions{r}#63, languages{r}#64, languages.byte{r}#65, languages.long{r}#66, languages.short{r}#67, last_name{r}#68, salary{r}#69, salary_change{r}#70, salary_change.int{r}#71, salary_change.keyword{r}#72, salary_change.long{r}#73, still_hired{r}#74, language_code{f()}#75, unmapped1{f(PotentiallyUnmappedKeywordEsField)}#76, unmapped2{f(PotentiallyUnmappedKeywordEsField)}#77]] - \_Eval[[null[LONG] AS avg_worked_seconds#52, null[DATETIME] AS birth_date#53, null[INTEGER] AS emp_no#54, null[KEYWORD] AS first_name#55, null[KEYWORD] AS gender#56, null[DOUBLE] AS height#57, null[DOUBLE] AS height.float#58, null[DOUBLE] AS height.half_float#59, null[DOUBLE] AS height.scaled_float#60, null[DATETIME] AS hire_date#61, null[BOOLEAN] AS is_rehired#62, null[KEYWORD] AS job_positions#63, null[INTEGER] AS languages#64, null[INTEGER] AS languages.byte#65, null[LONG] AS languages.long#66, null[INTEGER] AS languages.short#67, null[KEYWORD] AS last_name#68, null[INTEGER] AS salary#69, null[DOUBLE] AS salary_change#70, null[INTEGER] AS salary_change.int#71, null[KEYWORD] AS salary_change.keyword#72, null[LONG] AS salary_change.long#73, null[BOOLEAN] AS still_hired#74]] - \_Subquery[] - \_Project[[language_code{f()}#75, unmapped1{f(PotentiallyUnmappedKeywordEsField)}#76, unmapped2{f(PotentiallyUnmappedKeywordEsField)}#77]] - \_EsRelation[languages][language_code{f}#75, language_name{f}#78, unmapped1{f}#76, unmapped2{f}#77] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql deleted file mode 100644 index f48daedc4ab1d..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees, - (FROM languages | KEEP language_code, unmapped1, unmapped2) -| KEEP emp_no, language_code, unmapped1, unmapped2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected deleted file mode 100644 index 113ceff5421e3..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected +++ /dev/null @@ -1,13 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[emp_no{r}#0, language_code{r}#1, does_not_exist{r}#2]] - \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, language_code{r}#1, does_not_exist{r}#2]] - |_Project[[avg_worked_seconds{f()}#25, birth_date{f()}#26, emp_no{f()}#27, first_name{f()}#28, gender{f()}#29, height{f()}#30, height.float{f()}#31, height.half_float{f()}#32, height.scaled_float{f()}#33, hire_date{f()}#34, is_rehired{f()}#35, job_positions{f()}#36, languages{f()}#37, languages.byte{f()}#38, languages.long{f()}#39, languages.short{f()}#40, last_name{f()}#41, salary{f()}#42, salary_change{f()}#43, salary_change.int{f()}#44, salary_change.keyword{f()}#45, salary_change.long{f()}#46, still_hired{f()}#47, language_code{r}#48, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#49]] - | \_Eval[[null[INTEGER] AS language_code#48]] - | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, does_not_exist{f}#49] - \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f()}#73, does_not_exist{r}#74]] - \_Eval[[null[KEYWORD] AS does_not_exist#74]] - \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f()}#73]] - \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] - \_Subquery[] - \_Project[[language_code{f()}#73]] - \_EsRelation[languages][language_code{f}#73, language_name{f}#75, does_not_exist{f}#76] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql deleted file mode 100644 index 1b76ece4d7ba5..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees, (FROM languages | KEEP language_code) -| KEEP emp_no, language_code, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/analysis.expected deleted file mode 100644 index c66e2c8319dba..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/analysis.expected +++ /dev/null @@ -1,21 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[emp_no{r}#0, language_code{r}#1]] - \_Filter[$$does_not_exist$converted_to$long{r$}#2 > 0[INTEGER]] - \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, language_code{r}#1, language_name{r}#25, does_not_exist{r}#26, $$does_not_exist$converted_to$long{r$}#2]] - |_Project[[avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, language_code{r}#50, language_name{r}#51, does_not_exist{f}#52, $$does_not_exist$converted_to$long{r$}#53]] - | \_Eval[[TOLONG(does_not_exist{f}#52) AS $$does_not_exist$converted_to$long#53]] - | \_Eval[[null[INTEGER] AS language_code#50, null[KEYWORD] AS language_name#51]] - | \_EsRelation[employees][avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, does_not_exist{f}#52] - |_Project[[avg_worked_seconds{r}#54, birth_date{r}#55, emp_no{r}#56, first_name{r}#57, gender{r}#58, height{r}#59, height.float{r}#60, height.half_float{r}#61, height.scaled_float{r}#62, hire_date{r}#63, is_rehired{r}#64, job_positions{r}#65, languages{r}#66, languages.byte{r}#67, languages.long{r}#68, languages.short{r}#69, last_name{r}#70, salary{r}#71, salary_change{r}#72, salary_change.int{r}#73, salary_change.keyword{r}#74, salary_change.long{r}#75, still_hired{r}#76, language_code{f}#77, language_name{f}#78, does_not_exist{f}#79, $$does_not_exist$converted_to$long{r$}#80]] - | \_Eval[[TOLONG(does_not_exist{f}#79) AS $$does_not_exist$converted_to$long#80]] - | \_Eval[[null[LONG] AS avg_worked_seconds#54, null[DATETIME] AS birth_date#55, null[INTEGER] AS emp_no#56, null[KEYWORD] AS first_name#57, null[KEYWORD] AS gender#58, null[DOUBLE] AS height#59, null[DOUBLE] AS height.float#60, null[DOUBLE] AS height.half_float#61, null[DOUBLE] AS height.scaled_float#62, null[DATETIME] AS hire_date#63, null[BOOLEAN] AS is_rehired#64, null[KEYWORD] AS job_positions#65, null[INTEGER] AS languages#66, null[INTEGER] AS languages.byte#67, null[LONG] AS languages.long#68, null[INTEGER] AS languages.short#69, null[KEYWORD] AS last_name#70, null[INTEGER] AS salary#71, null[DOUBLE] AS salary_change#72, null[INTEGER] AS salary_change.int#73, null[KEYWORD] AS salary_change.keyword#74, null[LONG] AS salary_change.long#75, null[BOOLEAN] AS still_hired#76]] - | \_Subquery[] - | \_Filter[language_code{f}#77 > 0[INTEGER]] - | \_EsRelation[languages][language_code{f}#77, language_name{f}#78, does_not_exist{f}#79] - \_Project[[avg_worked_seconds{f}#81, birth_date{f}#82, emp_no{f}#83, first_name{f}#84, gender{f}#85, height{f}#86, height.float{f}#87, height.half_float{f}#88, height.scaled_float{f}#89, hire_date{f}#90, is_rehired{f}#91, job_positions{f}#92, languages{f}#93, languages.byte{f}#94, languages.long{f}#95, languages.short{f}#96, last_name{f}#97, salary{f}#98, salary_change{f}#99, salary_change.int{f}#100, salary_change.keyword{f}#101, salary_change.long{f}#102, still_hired{f}#103, language_code{r}#104, language_name{f}#105, does_not_exist{f}#106, $$does_not_exist$converted_to$long{r$}#107]] - \_Eval[[TOLONG(does_not_exist{f}#106) AS $$does_not_exist$converted_to$long#107]] - \_Subquery[] - \_LookupJoin[LEFT,[language_code{r}#104],[language_code{f}#108],false,null] - |_Eval[[languages{f}#93 AS language_code#104]] - | \_EsRelation[employees][avg_worked_seconds{f}#81, birth_date{f}#82, emp_no{f}#83, first_name{f}#84, gender{f}#85, height{f}#86, height.float{f}#87, height.half_float{f}#88, height.scaled_float{f}#89, hire_date{f}#90, is_rehired{f}#91, job_positions{f}#92, languages{f}#93, languages.byte{f}#94, languages.long{f}#95, languages.short{f}#96, last_name{f}#97, salary{f}#98, salary_change{f}#99, salary_change.int{f}#100, salary_change.keyword{f}#101, salary_change.long{f}#102, still_hired{f}#103, does_not_exist{f}#106] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}#108, language_name{f}#105] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/query.esql deleted file mode 100644 index 9e1ecb142ea61..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/load/query.esql +++ /dev/null @@ -1,5 +0,0 @@ -SET unmapped_fields="load"; FROM employees, - (FROM languages | WHERE language_code > 0), - (FROM employees | EVAL language_code = languages | LOOKUP JOIN languages_lookup ON language_code) -| WHERE does_not_exist::LONG > 0 -| KEEP emp_no, language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/analysis.expected deleted file mode 100644 index 88494026b12bd..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/analysis.expected +++ /dev/null @@ -1,23 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[emp_no{r}#0, language_code{r}#1]] - \_Filter[$$does_not_exist$converted_to$long{r$}#2 > 0[INTEGER]] - \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, language_code{r}#1, language_name{r}#25, does_not_exist{r}#26, $$does_not_exist$converted_to$long{r$}#2]] - |_Project[[avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, language_code{r}#50, language_name{r}#51, does_not_exist{r}#52, $$does_not_exist$converted_to$long{r$}#53]] - | \_Eval[[TOLONG(does_not_exist{r}#52) AS $$does_not_exist$converted_to$long#53]] - | \_Eval[[null[INTEGER] AS language_code#50, null[KEYWORD] AS language_name#51, null[NULL] AS does_not_exist#52]] - | \_EsRelation[employees][avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49] - |_Project[[avg_worked_seconds{r}#54, birth_date{r}#55, emp_no{r}#56, first_name{r}#57, gender{r}#58, height{r}#59, height.float{r}#60, height.half_float{r}#61, height.scaled_float{r}#62, hire_date{r}#63, is_rehired{r}#64, job_positions{r}#65, languages{r}#66, languages.byte{r}#67, languages.long{r}#68, languages.short{r}#69, last_name{r}#70, salary{r}#71, salary_change{r}#72, salary_change.int{r}#73, salary_change.keyword{r}#74, salary_change.long{r}#75, still_hired{r}#76, language_code{f}#77, language_name{f}#78, does_not_exist{r}#79, $$does_not_exist$converted_to$long{r$}#80]] - | \_Eval[[TOLONG(does_not_exist{r}#79) AS $$does_not_exist$converted_to$long#80]] - | \_Eval[[null[LONG] AS avg_worked_seconds#54, null[DATETIME] AS birth_date#55, null[INTEGER] AS emp_no#56, null[KEYWORD] AS first_name#57, null[KEYWORD] AS gender#58, null[DOUBLE] AS height#59, null[DOUBLE] AS height.float#60, null[DOUBLE] AS height.half_float#61, null[DOUBLE] AS height.scaled_float#62, null[DATETIME] AS hire_date#63, null[BOOLEAN] AS is_rehired#64, null[KEYWORD] AS job_positions#65, null[INTEGER] AS languages#66, null[INTEGER] AS languages.byte#67, null[LONG] AS languages.long#68, null[INTEGER] AS languages.short#69, null[KEYWORD] AS last_name#70, null[INTEGER] AS salary#71, null[DOUBLE] AS salary_change#72, null[INTEGER] AS salary_change.int#73, null[KEYWORD] AS salary_change.keyword#74, null[LONG] AS salary_change.long#75, null[BOOLEAN] AS still_hired#76]] - | \_Subquery[] - | \_Filter[language_code{f}#77 > 0[INTEGER]] - | \_Eval[[null[NULL] AS does_not_exist#79]] - | \_EsRelation[languages][language_code{f}#77, language_name{f}#78] - \_Project[[avg_worked_seconds{f}#81, birth_date{f}#82, emp_no{f}#83, first_name{f}#84, gender{f}#85, height{f}#86, height.float{f}#87, height.half_float{f}#88, height.scaled_float{f}#89, hire_date{f}#90, is_rehired{f}#91, job_positions{f}#92, languages{f}#93, languages.byte{f}#94, languages.long{f}#95, languages.short{f}#96, last_name{f}#97, salary{f}#98, salary_change{f}#99, salary_change.int{f}#100, salary_change.keyword{f}#101, salary_change.long{f}#102, still_hired{f}#103, language_code{r}#104, language_name{f}#105, does_not_exist{r}#106, $$does_not_exist$converted_to$long{r$}#107]] - \_Eval[[TOLONG(does_not_exist{r}#106) AS $$does_not_exist$converted_to$long#107]] - \_Subquery[] - \_LookupJoin[LEFT,[language_code{r}#104],[language_code{f}#108],false,null] - |_Eval[[languages{f}#93 AS language_code#104, null[NULL] AS does_not_exist#109]] - | \_EsRelation[employees][avg_worked_seconds{f}#81, birth_date{f}#82, emp_no{f}#83, first_name{f}#84, gender{f}#85, height{f}#86, height.float{f}#87, height.half_float{f}#88, height.scaled_float{f}#89, hire_date{f}#90, is_rehired{f}#91, job_positions{f}#92, languages{f}#93, languages.byte{f}#94, languages.long{f}#95, languages.short{f}#96, last_name{f}#97, salary{f}#98, salary_change{f}#99, salary_change.int{f}#100, salary_change.keyword{f}#101, salary_change.long{f}#102, still_hired{f}#103] - \_Eval[[null[NULL] AS does_not_exist#106]] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}#108, language_name{f}#105] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/query.esql deleted file mode 100644 index 1cae2badc15ab..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithLookupJoin/nullify/query.esql +++ /dev/null @@ -1,5 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees, - (FROM languages | WHERE language_code > 0), - (FROM employees | EVAL language_code = languages | LOOKUP JOIN languages_lookup ON language_code) -| WHERE does_not_exist::LONG > 0 -| KEEP emp_no, language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected deleted file mode 100644 index 7c4f1036413c8..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected +++ /dev/null @@ -1,11 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[emp_no{r}#0, max_ts{r}#1, does_not_exist{r}#2]] - \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, max_ts{r}#1, does_not_exist{r}#2]] - |_Project[[avg_worked_seconds{f()}#25, birth_date{f()}#26, emp_no{f()}#27, first_name{f()}#28, gender{f()}#29, height{f()}#30, height.float{f()}#31, height.half_float{f()}#32, height.scaled_float{f()}#33, hire_date{f()}#34, is_rehired{f()}#35, job_positions{f()}#36, languages{f()}#37, languages.byte{f()}#38, languages.long{f()}#39, languages.short{f()}#40, last_name{f()}#41, salary{f()}#42, salary_change{f()}#43, salary_change.int{f()}#44, salary_change.keyword{f()}#45, salary_change.long{f()}#46, still_hired{f()}#47, max_ts{r}#48, does_not_exist{r}#49]] - | \_Eval[[null[DATETIME] AS max_ts#48, null[KEYWORD] AS does_not_exist#49]] - | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] - \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, max_ts{r}#73, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74]] - \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] - \_Subquery[] - \_Aggregate[[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74],[MAX(@timestamp{f()}#75,true[BOOLEAN],PT0S[TIME_DURATION]) AS max_ts#73, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74]] - \_EsRelation[sample_data][@timestamp{f}#75, client_ip{f}#76, event_duration{f}#77, message{f}#78, does_not_exist{f}#74] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql deleted file mode 100644 index dabf6fc1b0e8c..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees, (FROM sample_data | STATS max_ts = MAX(@timestamp) BY does_not_exist) -| KEEP emp_no, max_ts, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/analysis.expected deleted file mode 100644 index 0eadb71bf5ba0..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#0) AS tbucket(1 hour)#1],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#2, tbucket(1 hour){r}#1]] - \_Filter[TOLONG(does_not_exist{f}#3) > 0[INTEGER]] - \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6, does_not_exist{f}#3] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/query.esql deleted file mode 100644 index b32e8bd6d23f4..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM sample_data -| WHERE does_not_exist::LONG > 0 -| STATS c = COUNT(*) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/analysis.expected deleted file mode 100644 index 91da106ed92ba..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#0) AS tbucket(1 hour)#1],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#2, tbucket(1 hour){r}#1]] - \_Filter[TOLONG(does_not_exist{r}#3) > 0[INTEGER]] - \_Eval[[null[NULL] AS does_not_exist#3]] - \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/query.esql deleted file mode 100644 index b6b417785892b..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucket/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; FROM sample_data -| WHERE does_not_exist::LONG > 0 -| STATS c = COUNT(*) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/load/query.esql deleted file mode 100644 index f2fed1cf47861..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| STATS c = COUNT(*) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/nullify/query.esql deleted file mode 100644 index 8f4b99c0e762b..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketFromIndexWithoutMappedTimestamp/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| STATS c = COUNT(*) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/analysis.expected deleted file mode 100644 index b94f828d0e124..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[TBUCKET(P1D[DATE_PERIOD],@timestamp{f}#0) AS tbucket(1 day)#1],[SUM(TODOUBLE(does_not_exist{f}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, tbucket(1 day){r}#1]] - \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/query.esql deleted file mode 100644 index f0d33fb33d8a2..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM sample_data -| STATS s = SUM(does_not_exist::DOUBLE) BY tbucket(1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/analysis.expected deleted file mode 100644 index b9d36a0af9fef..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[TBUCKET(P1D[DATE_PERIOD],@timestamp{f}#0) AS tbucket(1 day)#1],[SUM(TODOUBLE(does_not_exist{r}#2),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#3, tbucket(1 day){r}#1]] - \_Eval[[null[NULL] AS does_not_exist#2]] - \_EsRelation[sample_data][@timestamp{f}#0, client_ip{f}#4, event_duration{f}#5, message{f}#6] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/query.esql deleted file mode 100644 index dbe8b20220655..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTBucketWithUnmappedField/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM sample_data -| STATS s = SUM(does_not_exist::DOUBLE) BY tbucket(1 day) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/analysis.expected deleted file mode 100644 index 461abb31b2a3e..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000000[INTEGER],false,false] -\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(AVGOVERTIME(network.eth0.rx{f}#3,true[BOOLEAN],PT0S[TIME_DURATION]),true[BOOLEAN],PT0S[TIME_DURATION]) AS a#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] - \_Filter[TOLONG(does_not_exist{f}#5) > 0[INTEGER]] - \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#6, cluster{f}#7, event{f}#8, event_city{f}#9, event_city_boundary{f}#10, event_location{f}#11, event_log{f}#12, event_shape{f}#13, events_received{f}#14, network.bytes_in{f}#15, network.cost{f}#16, network.eth0.currently_connected_clients{f}#17, network.eth0.firmware_version{f}#18, network.eth0.last_up{f}#19, network.eth0.rx{f}#3, network.eth0.tx{f}#20, network.eth0.up{f}#21, network.total_bytes_in{f}#22, network.total_bytes_out{f}#23, network.total_cost{f}#24, pod{f}#25, region{f}#26, _timeseries{f}#0, does_not_exist{f}#5] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/query.esql deleted file mode 100644 index 07b29b5b8cfac..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; TS k8s -| WHERE does_not_exist::LONG > 0 -| STATS a = AVG_OVER_TIME(network.eth0.rx) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/analysis.expected deleted file mode 100644 index d9cd26163304f..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000000[INTEGER],false,false] -\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(AVGOVERTIME(network.eth0.rx{f}#3,true[BOOLEAN],PT0S[TIME_DURATION]),true[BOOLEAN],PT0S[TIME_DURATION]) AS a#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] - \_Filter[TOLONG(does_not_exist{r}#5) > 0[INTEGER]] - \_Eval[[null[NULL] AS does_not_exist#5]] - \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#6, cluster{f}#7, event{f}#8, event_city{f}#9, event_city_boundary{f}#10, event_location{f}#11, event_log{f}#12, event_shape{f}#13, events_received{f}#14, network.bytes_in{f}#15, network.cost{f}#16, network.eth0.currently_connected_clients{f}#17, network.eth0.firmware_version{f}#18, network.eth0.last_up{f}#19, network.eth0.rx{f}#3, network.eth0.tx{f}#20, network.eth0.up{f}#21, network.total_bytes_in{f}#22, network.total_bytes_out{f}#23, network.total_cost{f}#24, pod{f}#25, region{f}#26, _timeseries{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/query.esql deleted file mode 100644 index 3ae9a1aa9dbe9..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesAvgOverTime/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; TS k8s -| WHERE does_not_exist::LONG > 0 -| STATS a = AVG_OVER_TIME(network.eth0.rx) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/analysis.expected deleted file mode 100644 index e19e2e842bf54..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[@timestamp{f}#0, cluster{f}#1, x{r}#2]] - \_Eval[[TODOUBLE(does_not_exist{f}#3) + network.cost{f}#4 AS x#2]] - \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#0, client.ip{f}#5, cluster{f}#1, event{f}#6, event_city{f}#7, event_city_boundary{f}#8, event_location{f}#9, event_log{f}#10, event_shape{f}#11, events_received{f}#12, network.bytes_in{f}#13, network.cost{f}#4, network.eth0.currently_connected_clients{f}#14, network.eth0.firmware_version{f}#15, network.eth0.last_up{f}#16, network.eth0.rx{f}#17, network.eth0.tx{f}#18, network.eth0.up{f}#19, network.total_bytes_in{f}#20, network.total_bytes_out{f}#21, network.total_cost{f}#22, pod{f}#23, region{f}#24, does_not_exist{f}#3] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/query.esql deleted file mode 100644 index 94e371a53661c..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; TS k8s -| EVAL x = does_not_exist::DOUBLE + network.cost -| KEEP @timestamp, cluster, x diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/analysis.expected deleted file mode 100644 index 0b49d801279f5..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[@timestamp{f}#0, cluster{f}#1, x{r}#2]] - \_Eval[[TODOUBLE(does_not_exist{r}#3) + network.cost{f}#4 AS x#2]] - \_Eval[[null[NULL] AS does_not_exist#3]] - \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#0, client.ip{f}#5, cluster{f}#1, event{f}#6, event_city{f}#7, event_city_boundary{f}#8, event_location{f}#9, event_log{f}#10, event_shape{f}#11, events_received{f}#12, network.bytes_in{f}#13, network.cost{f}#4, network.eth0.currently_connected_clients{f}#14, network.eth0.firmware_version{f}#15, network.eth0.last_up{f}#16, network.eth0.rx{f}#17, network.eth0.tx{f}#18, network.eth0.up{f}#19, network.total_bytes_in{f}#20, network.total_bytes_out{f}#21, network.total_cost{f}#22, pod{f}#23, region{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/query.esql deleted file mode 100644 index a9a6f91b2b94b..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesEvalUnmapped/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; TS k8s -| EVAL x = does_not_exist::DOUBLE + network.cost -| KEEP @timestamp, cluster, x diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/analysis.expected deleted file mode 100644 index 4819c89f1c210..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[@timestamp{f}#0, cluster{f}#1, does_not_exist{f}#2]] - \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#0, client.ip{f}#3, cluster{f}#1, event{f}#4, event_city{f}#5, event_city_boundary{f}#6, event_location{f}#7, event_log{f}#8, event_shape{f}#9, events_received{f}#10, network.bytes_in{f}#11, network.cost{f}#12, network.eth0.currently_connected_clients{f}#13, network.eth0.firmware_version{f}#14, network.eth0.last_up{f}#15, network.eth0.rx{f}#16, network.eth0.tx{f}#17, network.eth0.up{f}#18, network.total_bytes_in{f}#19, network.total_bytes_out{f}#20, network.total_cost{f}#21, pod{f}#22, region{f}#23, does_not_exist{f}#2] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/query.esql deleted file mode 100644 index d872e477d1225..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; TS k8s -| KEEP @timestamp, cluster, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/analysis.expected deleted file mode 100644 index 6a20c2f90cbfd..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[@timestamp{f}#0, cluster{f}#1, does_not_exist{r}#2]] - \_Eval[[null[NULL] AS does_not_exist#2]] - \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#0, client.ip{f}#3, cluster{f}#1, event{f}#4, event_city{f}#5, event_city_boundary{f}#6, event_location{f}#7, event_log{f}#8, event_shape{f}#9, events_received{f}#10, network.bytes_in{f}#11, network.cost{f}#12, network.eth0.currently_connected_clients{f}#13, network.eth0.firmware_version{f}#14, network.eth0.last_up{f}#15, network.eth0.rx{f}#16, network.eth0.tx{f}#17, network.eth0.up{f}#18, network.total_bytes_in{f}#19, network.total_bytes_out{f}#20, network.total_cost{f}#21, pod{f}#22, region{f}#23] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/query.esql deleted file mode 100644 index c6b92a7280467..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesKeepUnmapped/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; TS k8s -| KEEP @timestamp, cluster, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/analysis.expected deleted file mode 100644 index 57b3580871a30..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000000[INTEGER],false,false] -\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(MAXOVERTIME(network.eth0.tx{f}#3,true[BOOLEAN],PT0S[TIME_DURATION]),true[BOOLEAN],PT0S[TIME_DURATION]) AS m#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] - \_Eval[[TODOUBLE(does_not_exist{f}#5) + 1[INTEGER] AS x#6]] - \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#7, cluster{f}#8, event{f}#9, event_city{f}#10, event_city_boundary{f}#11, event_location{f}#12, event_log{f}#13, event_shape{f}#14, events_received{f}#15, network.bytes_in{f}#16, network.cost{f}#17, network.eth0.currently_connected_clients{f}#18, network.eth0.firmware_version{f}#19, network.eth0.last_up{f}#20, network.eth0.rx{f}#21, network.eth0.tx{f}#3, network.eth0.up{f}#22, network.total_bytes_in{f}#23, network.total_bytes_out{f}#24, network.total_cost{f}#25, pod{f}#26, region{f}#27, _timeseries{f}#0, does_not_exist{f}#5] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/query.esql deleted file mode 100644 index 5d1d571c052d2..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; TS k8s -| EVAL x = does_not_exist::DOUBLE + 1 -| STATS m = MAX_OVER_TIME(network.eth0.tx) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/analysis.expected deleted file mode 100644 index 418f1280705a3..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000000[INTEGER],false,false] -\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(MAXOVERTIME(network.eth0.tx{f}#3,true[BOOLEAN],PT0S[TIME_DURATION]),true[BOOLEAN],PT0S[TIME_DURATION]) AS m#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] - \_Eval[[TODOUBLE(does_not_exist{r}#5) + 1[INTEGER] AS x#6]] - \_Eval[[null[NULL] AS does_not_exist#5]] - \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#7, cluster{f}#8, event{f}#9, event_city{f}#10, event_city_boundary{f}#11, event_location{f}#12, event_log{f}#13, event_shape{f}#14, events_received{f}#15, network.bytes_in{f}#16, network.cost{f}#17, network.eth0.currently_connected_clients{f}#18, network.eth0.firmware_version{f}#19, network.eth0.last_up{f}#20, network.eth0.rx{f}#21, network.eth0.tx{f}#3, network.eth0.up{f}#22, network.total_bytes_in{f}#23, network.total_bytes_out{f}#24, network.total_cost{f}#25, pod{f}#26, region{f}#27, _timeseries{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/query.esql deleted file mode 100644 index 8cfedb3e58a5c..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesMaxOverTime/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; TS k8s -| EVAL x = does_not_exist::DOUBLE + 1 -| STATS m = MAX_OVER_TIME(network.eth0.tx) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/analysis.expected deleted file mode 100644 index c60ce59bffa66..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000000[INTEGER],false,false] -\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(RATE(network.total_cost{f}#3,true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS r#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] - \_Filter[TOLONG(does_not_exist{f}#5) > 0[INTEGER]] - \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#6, cluster{f}#7, event{f}#8, event_city{f}#9, event_city_boundary{f}#10, event_location{f}#11, event_log{f}#12, event_shape{f}#13, events_received{f}#14, network.bytes_in{f}#15, network.cost{f}#16, network.eth0.currently_connected_clients{f}#17, network.eth0.firmware_version{f}#18, network.eth0.last_up{f}#19, network.eth0.rx{f}#20, network.eth0.tx{f}#21, network.eth0.up{f}#22, network.total_bytes_in{f}#23, network.total_bytes_out{f}#24, network.total_cost{f}#3, pod{f}#25, region{f}#26, _timeseries{f}#0, does_not_exist{f}#5] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/query.esql deleted file mode 100644 index 26c827ff5d107..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; TS k8s -| WHERE does_not_exist::LONG > 0 -| STATS r = RATE(network.total_cost) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/analysis.expected deleted file mode 100644 index e51c21b27f6a7..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000000[INTEGER],false,false] -\_TimeSeriesAggregate[[_timeseries{f}#0, TBUCKET(PT1H[TIME_DURATION],@timestamp{f}#1) AS tbucket(1 hour)#2],[VALUES(RATE(network.total_cost{f}#3,true[BOOLEAN],PT0S[TIME_DURATION],@timestamp{f}#1),true[BOOLEAN],PT0S[TIME_DURATION]) AS r#4, tbucket(1 hour){r}#2],null,@timestamp{f}#1] - \_Filter[TOLONG(does_not_exist{r}#5) > 0[INTEGER]] - \_Eval[[null[NULL] AS does_not_exist#5]] - \_EsRelation[k8s][TIME_SERIES][@timestamp{f}#1, client.ip{f}#6, cluster{f}#7, event{f}#8, event_city{f}#9, event_city_boundary{f}#10, event_location{f}#11, event_log{f}#12, event_shape{f}#13, events_received{f}#14, network.bytes_in{f}#15, network.cost{f}#16, network.eth0.currently_connected_clients{f}#17, network.eth0.firmware_version{f}#18, network.eth0.last_up{f}#19, network.eth0.rx{f}#20, network.eth0.tx{f}#21, network.eth0.up{f}#22, network.total_bytes_in{f}#23, network.total_bytes_out{f}#24, network.total_cost{f}#3, pod{f}#25, region{f}#26, _timeseries{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/query.esql deleted file mode 100644 index 142d352cd603f..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRate/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; TS k8s -| WHERE does_not_exist::LONG > 0 -| STATS r = RATE(network.total_cost) BY tbucket(1 hour) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateWithUnmappedGroupBy/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateWithUnmappedGroupBy/nullify/query.esql deleted file mode 100644 index f084c1078693a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTimeSeriesRateWithUnmappedGroupBy/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; TS k8s -| STATS r = RATE(network.total_cost) BY tbucket(1 hour), does_not_exist From 9361f091c02cd80d48c8c1d1a00e3366c78a90ab Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Sun, 15 Mar 2026 19:33:16 +0200 Subject: [PATCH 099/137] ESQL: Remove duplicates and cleanup orphans --- .../analysis/AnalyzerUnmappedGoldenTests.java | 26 -------------- .../testEvalReplace/load/analysis.expected | 4 --- .../testEvalReplace/load/query.esql | 3 -- .../testEvalReplace/nullify/analysis.expected | 5 --- .../testEvalReplace/nullify/query.esql | 3 -- .../testFork/load/analysis.expected | 13 ------- .../testFork/load/query.esql | 3 -- .../testForkWithEval/load/analysis.expected | 14 -------- .../testForkWithEval/load/query.esql | 3 -- .../testForkWithStats/load/analysis.expected | 15 -------- .../testForkWithStats/load/query.esql | 4 --- .../testFuse/load/analysis.expected | 15 -------- .../testFuse/load/query.esql | 4 --- .../testFuseLinear/load/analysis.expected | 18 ---------- .../testFuseLinear/load/query.esql | 4 --- .../testFuseWithEval/load/analysis.expected | 16 --------- .../testFuseWithEval/load/query.esql | 4 --- .../testInlineStats/load/analysis.expected | 3 -- .../testInlineStats/load/query.esql | 2 -- .../testInlineStats/nullify/analysis.expected | 3 -- .../testInlineStats/nullify/query.esql | 2 -- .../testKeepThenEval/load/analysis.expected | 4 --- .../testKeepThenEval/load/query.esql | 3 -- .../nullify/analysis.expected | 5 --- .../testKeepThenEval/nullify/query.esql | 3 -- .../testLookupJoin/load/analysis.expected | 5 --- .../testLookupJoin/load/query.esql | 3 -- .../load/analysis.expected | 6 ---- .../testLookupJoinWithFilter/load/query.esql | 4 --- .../testRenameEval/load/analysis.expected | 4 --- .../testRenameEval/load/query.esql | 3 -- .../testRenameEval/nullify/analysis.expected | 5 --- .../testRenameEval/nullify/query.esql | 3 -- .../testRow/load/query.esql | 3 -- .../load/analysis.expected | 3 -- .../testStatsAggFiltering/load/query.esql | 2 -- .../nullify/analysis.expected | 4 --- .../testStatsAggFiltering/nullify/query.esql | 2 -- .../load/analysis.expected | 11 ------ .../load/query.esql | 3 -- .../load/analysis.expected | 13 ------- .../testSubqueryKeepUnmapped/load/query.esql | 2 -- .../load/analysis.expected | 11 ------ .../testSubqueryWithStats/load/query.esql | 2 -- .../nullify/analysis.expected | 35 ------------------- .../nullify/query.esql | 13 ------- 46 files changed, 316 deletions(-) delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRow/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/query.esql diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java index 178c4d6c66d25..e3faf11ef4b5d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -211,13 +211,6 @@ public void testStatsMixedAndExpressions() throws Exception { """, STAGES); } - public void testInlineStats() throws Exception { - runTests(""" - FROM employees - | STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 - """); - } - public void testInlineStatsMixed() throws Exception { runTests(""" FROM employees @@ -607,25 +600,6 @@ public void testSubquerysMixAndLookupJoinNullify() throws Exception { """, STAGES); } - public void testSubquerysMixAndLookupJoinLoad() throws Exception { - assumeTrue("Requires subquery in FROM command support", EsqlCapabilities.Cap.SUBQUERY_IN_FROM_COMMAND.isEnabled()); - runTestsNullifyOnly(""" - FROM employees, - (FROM languages - | WHERE language_code > 10 - | RENAME language_name as languageName), - (FROM sample_data - | STATS max(@timestamp)), - (FROM employees - | EVAL language_code = languages - | LOOKUP JOIN languages_lookup ON language_code) - | WHERE emp_no > 10000 OR does_not_exist1::LONG < 10 - | STATS count(*) BY emp_no, language_code, does_not_exist2 - | RENAME emp_no AS empNo, language_code AS languageCode - | MV_EXPAND languageCode - """, STAGES); - } - public void testSubquerysWithMainAndStatsOnly() throws Exception { assumeTrue("Requires subquery in FROM command support", EsqlCapabilities.Cap.SUBQUERY_IN_FROM_COMMAND.isEnabled()); runTestsNullifyOnly(""" diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected deleted file mode 100644 index ffb2c79dd6cd0..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[42[INTEGER] AS does_not_exist_field#0]] - \_Eval[[TODOUBLE(does_not_exist_field{f}#1) + 1[INTEGER] AS x#2]] - \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist_field{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/query.esql deleted file mode 100644 index 826ae0ac8f745..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| EVAL x = does_not_exist_field::DOUBLE + 1 -| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected deleted file mode 100644 index 5ce8713e6a882..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[42[INTEGER] AS does_not_exist_field#0]] - \_Eval[[TODOUBLE(does_not_exist_field{r}#1) + 1[INTEGER] AS x#2]] - \_Eval[[null[NULL] AS does_not_exist_field#1]] - \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql deleted file mode 100644 index 241e39491fa9a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testEvalReplace/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| EVAL x = does_not_exist_field::DOUBLE + 1 -| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected deleted file mode 100644 index cd1fc9b47d736..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/analysis.expected +++ /dev/null @@ -1,13 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, _fork{r}#24]] - |_Limit[1000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f()}#25, birth_date{f()}#26, emp_no{f()}#27, first_name{f()}#28, gender{f()}#29, height{f()}#30, height.float{f()}#31, height.half_float{f()}#32, height.scaled_float{f()}#33, hire_date{f()}#34, is_rehired{f()}#35, job_positions{f()}#36, languages{f()}#37, languages.byte{f()}#38, languages.long{f()}#39, languages.short{f()}#40, last_name{f()}#41, salary{f()}#42, salary_change{f()}#43, salary_change.int{f()}#44, salary_change.keyword{f()}#45, salary_change.long{f()}#46, still_hired{f()}#47, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#48, _fork{r}#49]] - | \_Eval[[fork1[KEYWORD] AS _fork#49]] - | \_Filter[TOLONG(does_not_exist{f}#48) > 0[INTEGER]] - | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, does_not_exist{f}#48] - \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f()}#50, birth_date{f()}#51, emp_no{f()}#52, first_name{f()}#53, gender{f()}#54, height{f()}#55, height.float{f()}#56, height.half_float{f()}#57, height.scaled_float{f()}#58, hire_date{f()}#59, is_rehired{f()}#60, job_positions{f()}#61, languages{f()}#62, languages.byte{f()}#63, languages.long{f()}#64, languages.short{f()}#65, last_name{f()}#66, salary{f()}#67, salary_change{f()}#68, salary_change.int{f()}#69, salary_change.keyword{f()}#70, salary_change.long{f()}#71, still_hired{f()}#72, does_not_exist{r}#73, _fork{r}#49]] - \_Eval[[null[KEYWORD] AS does_not_exist#73]] - \_Eval[[fork2[KEYWORD] AS _fork#49]] - \_Filter[emp_no{f}#52 > 0[INTEGER]] - \_EsRelation[employees][avg_worked_seconds{f}#50, birth_date{f}#51, emp_no{f}#52, first_name{f}#53, gender{f}#54, height{f}#55, height.float{f}#56, height.half_float{f}#57, height.scaled_float{f}#58, hire_date{f}#59, is_rehired{f}#60, job_positions{f}#61, languages{f}#62, languages.byte{f}#63, languages.long{f}#64, languages.short{f}#65, last_name{f}#66, salary{f}#67, salary_change{f}#68, salary_change.int{f}#69, salary_change.keyword{f}#70, salary_change.long{f}#71, still_hired{f}#72] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql deleted file mode 100644 index 1b2a31d2f6afd..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFork/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| FORK (WHERE does_not_exist::LONG > 0) - (WHERE emp_no > 0) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected deleted file mode 100644 index 5230e1078a6f8..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/analysis.expected +++ /dev/null @@ -1,14 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Fork[[avg_worked_seconds{r}#0, birth_date{r}#1, emp_no{r}#2, first_name{r}#3, gender{r}#4, height{r}#5, height.float{r}#6, height.half_float{r}#7, height.scaled_float{r}#8, hire_date{r}#9, is_rehired{r}#10, job_positions{r}#11, languages{r}#12, languages.byte{r}#13, languages.long{r}#14, languages.short{r}#15, last_name{r}#16, salary{r}#17, salary_change{r}#18, salary_change.int{r}#19, salary_change.keyword{r}#20, salary_change.long{r}#21, still_hired{r}#22, does_not_exist{r}#23, x{r}#24, _fork{r}#25, y{r}#26]] - |_Limit[1000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f()}#27, birth_date{f()}#28, emp_no{f()}#29, first_name{f()}#30, gender{f()}#31, height{f()}#32, height.float{f()}#33, height.half_float{f()}#34, height.scaled_float{f()}#35, hire_date{f()}#36, is_rehired{f()}#37, job_positions{f()}#38, languages{f()}#39, languages.byte{f()}#40, languages.long{f()}#41, languages.short{f()}#42, last_name{f()}#43, salary{f()}#44, salary_change{f()}#45, salary_change.int{f()}#46, salary_change.keyword{f()}#47, salary_change.long{f()}#48, still_hired{f()}#49, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#50, x{r}#51, _fork{r}#52, y{r}#53]] - | \_Eval[[null[INTEGER] AS y#53]] - | \_Eval[[fork1[KEYWORD] AS _fork#52]] - | \_Eval[[TODOUBLE(does_not_exist{f}#50) + 1[INTEGER] AS x#51]] - | \_EsRelation[employees][avg_worked_seconds{f}#27, birth_date{f}#28, emp_no{f}#29, first_name{f}#30, gender{f}#31, height{f}#32, height.float{f}#33, height.half_float{f}#34, height.scaled_float{f}#35, hire_date{f}#36, is_rehired{f}#37, job_positions{f}#38, languages{f}#39, languages.byte{f}#40, languages.long{f}#41, languages.short{f}#42, last_name{f}#43, salary{f}#44, salary_change{f}#45, salary_change.int{f}#46, salary_change.keyword{f}#47, salary_change.long{f}#48, still_hired{f}#49, does_not_exist{f}#50] - \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f()}#54, birth_date{f()}#55, emp_no{f()}#56, first_name{f()}#57, gender{f()}#58, height{f()}#59, height.float{f()}#60, height.half_float{f()}#61, height.scaled_float{f()}#62, hire_date{f()}#63, is_rehired{f()}#64, job_positions{f()}#65, languages{f()}#66, languages.byte{f()}#67, languages.long{f()}#68, languages.short{f()}#69, last_name{f()}#70, salary{f()}#71, salary_change{f()}#72, salary_change.int{f()}#73, salary_change.keyword{f()}#74, salary_change.long{f()}#75, still_hired{f()}#76, does_not_exist{r}#77, x{r}#78, _fork{r}#52, y{r}#79]] - \_Eval[[null[KEYWORD] AS does_not_exist#77, null[DOUBLE] AS x#78]] - \_Eval[[fork2[KEYWORD] AS _fork#52]] - \_Eval[[emp_no{f}#56 + 1[INTEGER] AS y#79]] - \_EsRelation[employees][avg_worked_seconds{f}#54, birth_date{f}#55, emp_no{f}#56, first_name{f}#57, gender{f}#58, height{f}#59, height.float{f}#60, height.half_float{f}#61, height.scaled_float{f}#62, hire_date{f}#63, is_rehired{f}#64, job_positions{f}#65, languages{f}#66, languages.byte{f}#67, languages.long{f}#68, languages.short{f}#69, last_name{f}#70, salary{f}#71, salary_change{f}#72, salary_change.int{f}#73, salary_change.keyword{f}#74, salary_change.long{f}#75, still_hired{f}#76] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql deleted file mode 100644 index f007f2dec96ca..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithEval/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| FORK (EVAL x = does_not_exist::DOUBLE + 1) - (EVAL y = emp_no + 1) diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected deleted file mode 100644 index 3b3a8d51f9ff4..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/analysis.expected +++ /dev/null @@ -1,15 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_OrderBy[[Order[does_not_exist{r}#0,ASC,LAST]]] - \_Fork[[c{r}#1, does_not_exist{r}#0, _fork{r}#2, d{r}#3]] - |_Limit[1000[INTEGER],false,false] - | \_Project[[c{r}#4, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#5, _fork{r}#6, d{r}#7]] - | \_Eval[[null[DOUBLE] AS d#7]] - | \_Eval[[fork1[KEYWORD] AS _fork#6]] - | \_Aggregate[[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#5],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#4, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#5]] - | \_EsRelation[employees][avg_worked_seconds{f}#8, birth_date{f}#9, emp_no{f}#10, first_name{f}#11, gender{f}#12, height{f}#13, height.float{f}#14, height.half_float{f}#15, height.scaled_float{f}#16, hire_date{f}#17, is_rehired{f}#18, job_positions{f}#19, languages{f}#20, languages.byte{f}#21, languages.long{f}#22, languages.short{f}#23, last_name{f}#24, salary{f}#25, salary_change{f}#26, salary_change.int{f}#27, salary_change.keyword{f}#28, salary_change.long{f}#29, still_hired{f}#30, does_not_exist{f}#5] - \_Limit[1000[INTEGER],false,false] - \_Project[[c{r}#31, does_not_exist{r}#32, _fork{r}#6, d{r}#33]] - \_Eval[[null[LONG] AS c#31, null[KEYWORD] AS does_not_exist#32]] - \_Eval[[fork2[KEYWORD] AS _fork#6]] - \_Aggregate[[],[AVG(TODOUBLE(salary{f()}#34),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS d#33]] - \_EsRelation[employees][avg_worked_seconds{f}#35, birth_date{f}#36, emp_no{f}#37, first_name{f}#38, gender{f}#39, height{f}#40, height.float{f}#41, height.half_float{f}#42, height.scaled_float{f}#43, hire_date{f}#44, is_rehired{f}#45, job_positions{f}#46, languages{f}#47, languages.byte{f}#48, languages.long{f}#49, languages.short{f}#50, last_name{f}#51, salary{f}#34, salary_change{f}#52, salary_change.int{f}#53, salary_change.keyword{f}#54, salary_change.long{f}#55, still_hired{f}#56] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql deleted file mode 100644 index 3a52496cdfc84..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testForkWithStats/load/query.esql +++ /dev/null @@ -1,4 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| FORK (STATS c = COUNT(*) BY does_not_exist) - (STATS d = AVG(salary::DOUBLE)) -| SORT does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected deleted file mode 100644 index 21a0b60c54fbc..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/analysis.expected +++ /dev/null @@ -1,15 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(_fork{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#55]] - \_FuseScoreEval[_score{r}#2,_fork{r}#54,RRF,null] - \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, _fork{r}#54]] - |_Limit[1000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f()}#56, birth_date{f()}#57, emp_no{f()}#58, first_name{f()}#59, gender{f()}#60, height{f()}#61, height.float{f()}#62, height.half_float{f()}#63, height.scaled_float{f()}#64, hire_date{f()}#65, is_rehired{f()}#66, job_positions{f()}#67, languages{f()}#68, languages.byte{f()}#69, languages.long{f()}#70, languages.short{f()}#71, last_name{f()}#72, salary{f()}#73, salary_change{f()}#74, salary_change.int{f()}#75, salary_change.keyword{f()}#76, salary_change.long{f()}#77, still_hired{f()}#78, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#82, _fork{r}#83]] - | \_Eval[[fork1[KEYWORD] AS _fork#83]] - | \_Filter[TOLONG(does_not_exist{f}#82) > 0[INTEGER]] - | \_EsRelation[employees][avg_worked_seconds{f}#56, birth_date{f}#57, emp_no{f}#58, first_name{f}#59, gender{f}#60, height{f}#61, height.float{f}#62, height.half_float{f}#63, height.scaled_float{f}#64, hire_date{f}#65, is_rehired{f}#66, job_positions{f}#67, languages{f}#68, languages.byte{f}#69, languages.long{f}#70, languages.short{f}#71, last_name{f}#72, salary{f}#73, salary_change{f}#74, salary_change.int{f}#75, salary_change.keyword{f}#76, salary_change.long{f}#77, still_hired{f}#78, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{f}#82] - \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f()}#84, birth_date{f()}#85, emp_no{f()}#86, first_name{f()}#87, gender{f()}#88, height{f()}#89, height.float{f()}#90, height.half_float{f()}#91, height.scaled_float{f()}#92, hire_date{f()}#93, is_rehired{f()}#94, job_positions{f()}#95, languages{f()}#96, languages.byte{f()}#97, languages.long{f()}#98, languages.short{f()}#99, last_name{f()}#100, salary{f()}#101, salary_change{f()}#102, salary_change.int{f()}#103, salary_change.keyword{f()}#104, salary_change.long{f()}#105, still_hired{f()}#106, _score{m}#79, _index{m}#80, _id{m}#81, does_not_exist{r}#107, _fork{r}#83]] - \_Eval[[null[KEYWORD] AS does_not_exist#107]] - \_Eval[[fork2[KEYWORD] AS _fork#83]] - \_Filter[emp_no{f}#86 > 0[INTEGER]] - \_EsRelation[employees][avg_worked_seconds{f}#84, birth_date{f}#85, emp_no{f}#86, first_name{f}#87, gender{f}#88, height{f}#89, height.float{f}#90, height.half_float{f}#91, height.scaled_float{f}#92, hire_date{f}#93, is_rehired{f}#94, job_positions{f}#95, languages{f}#96, languages.byte{f}#97, languages.long{f}#98, languages.short{f}#99, last_name{f}#100, salary{f}#101, salary_change{f}#102, salary_change.int{f}#103, salary_change.keyword{f}#104, salary_change.long{f}#105, still_hired{f}#106, _score{m}#79, _index{m}#80, _id{m}#81] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql deleted file mode 100644 index 2217f682e64de..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuse/load/query.esql +++ /dev/null @@ -1,4 +0,0 @@ -SET unmapped_fields="load"; FROM employees METADATA _score, _index, _id -| FORK (WHERE does_not_exist::LONG > 0) - (WHERE emp_no > 0) -| FUSE diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected deleted file mode 100644 index caa8b7855cbfc..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/analysis.expected +++ /dev/null @@ -1,18 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(x{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS x#55, VALUES(_fork{r}#56,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#57, VALUES(y{r}#58,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#59]] - \_FuseScoreEval[_score{r}#2,_fork{r}#56,LINEAR,null] - \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, x{r}#54, _fork{r}#56, y{r}#58]] - |_Limit[1000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f()}#60, birth_date{f()}#61, emp_no{f()}#62, first_name{f()}#63, gender{f()}#64, height{f()}#65, height.float{f()}#66, height.half_float{f()}#67, height.scaled_float{f()}#68, hire_date{f()}#69, is_rehired{f()}#70, job_positions{f()}#71, languages{f()}#72, languages.byte{f()}#73, languages.long{f()}#74, languages.short{f()}#75, last_name{f()}#76, salary{f()}#77, salary_change{f()}#78, salary_change.int{f()}#79, salary_change.keyword{f()}#80, salary_change.long{f()}#81, still_hired{f()}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#86, x{r}#87, _fork{r}#88, y{r}#89]] - | \_Eval[[null[INTEGER] AS y#89]] - | \_Eval[[fork1[KEYWORD] AS _fork#88]] - | \_Eval[[1[INTEGER] AS x#87]] - | \_Filter[TOLONG(does_not_exist{f}#86) > 0[INTEGER]] - | \_EsRelation[employees][avg_worked_seconds{f}#60, birth_date{f}#61, emp_no{f}#62, first_name{f}#63, gender{f}#64, height{f}#65, height.float{f}#66, height.half_float{f}#67, height.scaled_float{f}#68, hire_date{f}#69, is_rehired{f}#70, job_positions{f}#71, languages{f}#72, languages.byte{f}#73, languages.long{f}#74, languages.short{f}#75, last_name{f}#76, salary{f}#77, salary_change{f}#78, salary_change.int{f}#79, salary_change.keyword{f}#80, salary_change.long{f}#81, still_hired{f}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f}#86] - \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f()}#90, birth_date{f()}#91, emp_no{f()}#92, first_name{f()}#93, gender{f()}#94, height{f()}#95, height.float{f()}#96, height.half_float{f()}#97, height.scaled_float{f()}#98, hire_date{f()}#99, is_rehired{f()}#100, job_positions{f()}#101, languages{f()}#102, languages.byte{f()}#103, languages.long{f()}#104, languages.short{f()}#105, last_name{f()}#106, salary{f()}#107, salary_change{f()}#108, salary_change.int{f()}#109, salary_change.keyword{f()}#110, salary_change.long{f()}#111, still_hired{f()}#112, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#113, x{r}#114, _fork{r}#88, y{r}#115]] - \_Eval[[null[KEYWORD] AS does_not_exist#113, null[INTEGER] AS x#114]] - \_Eval[[fork2[KEYWORD] AS _fork#88]] - \_Eval[[2[INTEGER] AS y#115]] - \_Filter[emp_no{f}#92 > 0[INTEGER]] - \_EsRelation[employees][avg_worked_seconds{f}#90, birth_date{f}#91, emp_no{f}#92, first_name{f}#93, gender{f}#94, height{f}#95, height.float{f}#96, height.half_float{f}#97, height.scaled_float{f}#98, hire_date{f}#99, is_rehired{f}#100, job_positions{f}#101, languages{f}#102, languages.byte{f}#103, languages.long{f}#104, languages.short{f}#105, last_name{f}#106, salary{f}#107, salary_change{f}#108, salary_change.int{f}#109, salary_change.keyword{f}#110, salary_change.long{f}#111, still_hired{f}#112, _score{m}#83, _index{m}#84, _id{m}#85] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql deleted file mode 100644 index 6ca46384903c8..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseLinear/load/query.esql +++ /dev/null @@ -1,4 +0,0 @@ -SET unmapped_fields="load"; FROM employees METADATA _score, _index, _id -| FORK (WHERE does_not_exist::LONG > 0 | EVAL x = 1) - (WHERE emp_no > 0 | EVAL y = 2) -| FUSE LINEAR diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected deleted file mode 100644 index 8a3d0ec4a83d7..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/analysis.expected +++ /dev/null @@ -1,16 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[_id{r}#0, _index{r}#1],[SUM(_score{r}#2,true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS _score#3, VALUES(avg_worked_seconds{r}#4,true[BOOLEAN],PT0S[TIME_DURATION]) AS avg_worked_seconds#5, VALUES(birth_date{r}#6,true[BOOLEAN],PT0S[TIME_DURATION]) AS birth_date#7, VALUES(emp_no{r}#8,true[BOOLEAN],PT0S[TIME_DURATION]) AS emp_no#9, VALUES(first_name{r}#10,true[BOOLEAN],PT0S[TIME_DURATION]) AS first_name#11, VALUES(gender{r}#12,true[BOOLEAN],PT0S[TIME_DURATION]) AS gender#13, VALUES(height{r}#14,true[BOOLEAN],PT0S[TIME_DURATION]) AS height#15, VALUES(height.float{r}#16,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.float#17, VALUES(height.half_float{r}#18,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.half_float#19, VALUES(height.scaled_float{r}#20,true[BOOLEAN],PT0S[TIME_DURATION]) AS height.scaled_float#21, VALUES(hire_date{r}#22,true[BOOLEAN],PT0S[TIME_DURATION]) AS hire_date#23, VALUES(is_rehired{r}#24,true[BOOLEAN],PT0S[TIME_DURATION]) AS is_rehired#25, VALUES(job_positions{r}#26,true[BOOLEAN],PT0S[TIME_DURATION]) AS job_positions#27, VALUES(languages{r}#28,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages#29, VALUES(languages.byte{r}#30,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.byte#31, VALUES(languages.long{r}#32,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.long#33, VALUES(languages.short{r}#34,true[BOOLEAN],PT0S[TIME_DURATION]) AS languages.short#35, VALUES(last_name{r}#36,true[BOOLEAN],PT0S[TIME_DURATION]) AS last_name#37, VALUES(salary{r}#38,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary#39, VALUES(salary_change{r}#40,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change#41, VALUES(salary_change.int{r}#42,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.int#43, VALUES(salary_change.keyword{r}#44,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.keyword#45, VALUES(salary_change.long{r}#46,true[BOOLEAN],PT0S[TIME_DURATION]) AS salary_change.long#47, VALUES(still_hired{r}#48,true[BOOLEAN],PT0S[TIME_DURATION]) AS still_hired#49, VALUES(_index{r}#1,true[BOOLEAN],PT0S[TIME_DURATION]) AS _index#50, VALUES(_id{r}#0,true[BOOLEAN],PT0S[TIME_DURATION]) AS _id#51, VALUES(does_not_exist{r}#52,true[BOOLEAN],PT0S[TIME_DURATION]) AS does_not_exist#53, VALUES(x{r}#54,true[BOOLEAN],PT0S[TIME_DURATION]) AS x#55, VALUES(_fork{r}#56,true[BOOLEAN],PT0S[TIME_DURATION]) AS _fork#57, VALUES(y{r}#58,true[BOOLEAN],PT0S[TIME_DURATION]) AS y#59]] - \_FuseScoreEval[_score{r}#2,_fork{r}#56,RRF,null] - \_Fork[[avg_worked_seconds{r}#4, birth_date{r}#6, emp_no{r}#8, first_name{r}#10, gender{r}#12, height{r}#14, height.float{r}#16, height.half_float{r}#18, height.scaled_float{r}#20, hire_date{r}#22, is_rehired{r}#24, job_positions{r}#26, languages{r}#28, languages.byte{r}#30, languages.long{r}#32, languages.short{r}#34, last_name{r}#36, salary{r}#38, salary_change{r}#40, salary_change.int{r}#42, salary_change.keyword{r}#44, salary_change.long{r}#46, still_hired{r}#48, _score{r}#2, _index{r}#1, _id{r}#0, does_not_exist{r}#52, x{r}#54, _fork{r}#56, y{r}#58]] - |_Limit[1000[INTEGER],false,false] - | \_Project[[avg_worked_seconds{f()}#60, birth_date{f()}#61, emp_no{f()}#62, first_name{f()}#63, gender{f()}#64, height{f()}#65, height.float{f()}#66, height.half_float{f()}#67, height.scaled_float{f()}#68, hire_date{f()}#69, is_rehired{f()}#70, job_positions{f()}#71, languages{f()}#72, languages.byte{f()}#73, languages.long{f()}#74, languages.short{f()}#75, last_name{f()}#76, salary{f()}#77, salary_change{f()}#78, salary_change.int{f()}#79, salary_change.keyword{f()}#80, salary_change.long{f()}#81, still_hired{f()}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#86, x{r}#87, _fork{r}#88, y{r}#89]] - | \_Eval[[null[INTEGER] AS y#89]] - | \_Eval[[fork1[KEYWORD] AS _fork#88]] - | \_Eval[[TODOUBLE(does_not_exist{f}#86) + 1[INTEGER] AS x#87]] - | \_EsRelation[employees][avg_worked_seconds{f}#60, birth_date{f}#61, emp_no{f}#62, first_name{f}#63, gender{f}#64, height{f}#65, height.float{f}#66, height.half_float{f}#67, height.scaled_float{f}#68, hire_date{f}#69, is_rehired{f}#70, job_positions{f}#71, languages{f}#72, languages.byte{f}#73, languages.long{f}#74, languages.short{f}#75, last_name{f}#76, salary{f}#77, salary_change{f}#78, salary_change.int{f}#79, salary_change.keyword{f}#80, salary_change.long{f}#81, still_hired{f}#82, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{f}#86] - \_Limit[1000[INTEGER],false,false] - \_Project[[avg_worked_seconds{f()}#90, birth_date{f()}#91, emp_no{f()}#92, first_name{f()}#93, gender{f()}#94, height{f()}#95, height.float{f()}#96, height.half_float{f()}#97, height.scaled_float{f()}#98, hire_date{f()}#99, is_rehired{f()}#100, job_positions{f()}#101, languages{f()}#102, languages.byte{f()}#103, languages.long{f()}#104, languages.short{f()}#105, last_name{f()}#106, salary{f()}#107, salary_change{f()}#108, salary_change.int{f()}#109, salary_change.keyword{f()}#110, salary_change.long{f()}#111, still_hired{f()}#112, _score{m}#83, _index{m}#84, _id{m}#85, does_not_exist{r}#113, x{r}#114, _fork{r}#88, y{r}#115]] - \_Eval[[null[KEYWORD] AS does_not_exist#113, null[DOUBLE] AS x#114]] - \_Eval[[fork2[KEYWORD] AS _fork#88]] - \_Eval[[emp_no{f}#92 + 1[INTEGER] AS y#115]] - \_EsRelation[employees][avg_worked_seconds{f}#90, birth_date{f}#91, emp_no{f}#92, first_name{f}#93, gender{f}#94, height{f}#95, height.float{f}#96, height.half_float{f}#97, height.scaled_float{f}#98, hire_date{f}#99, is_rehired{f}#100, job_positions{f}#101, languages{f}#102, languages.byte{f}#103, languages.long{f}#104, languages.short{f}#105, last_name{f}#106, salary{f}#107, salary_change{f}#108, salary_change.int{f}#109, salary_change.keyword{f}#110, salary_change.long{f}#111, still_hired{f}#112, _score{m}#83, _index{m}#84, _id{m}#85] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql deleted file mode 100644 index 28caa1c3f1e98..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testFuseWithEval/load/query.esql +++ /dev/null @@ -1,4 +0,0 @@ -SET unmapped_fields="load"; FROM employees METADATA _score, _index, _id -| FORK (EVAL x = does_not_exist::DOUBLE + 1) - (EVAL y = emp_no + 1) -| FUSE RRF diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected deleted file mode 100644 index d8965ede4d87d..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0],[SUM(TODOUBLE(does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#1),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#2, does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0]] - \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0, does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/query.esql deleted file mode 100644 index 4b45cf86d8cb5..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected deleted file mode 100644 index 27b179dff2e21..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[does_not_exist2{f}#0],[SUM(TODOUBLE(does_not_exist1{f}#1),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#2, does_not_exist2{f}#0]] - \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist2{f}#0, does_not_exist1{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql deleted file mode 100644 index 29d53f6beba5b..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected deleted file mode 100644 index 01fc4148688e2..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[42[INTEGER] AS does_not_exist_field#0]] - \_Project[[does_not_exist_field{f(PotentiallyUnmappedKeywordEsField)}#1]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist_field{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/query.esql deleted file mode 100644 index 945f0e290ca38..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| KEEP does_not_exist_field -| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected deleted file mode 100644 index f95ae9f74e6dc..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[42[INTEGER] AS does_not_exist_field#0]] - \_Project[[does_not_exist_field{r}#1]] - \_Eval[[null[NULL] AS does_not_exist_field#1]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql deleted file mode 100644 index 4337b35ba4b2e..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testKeepThenEval/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| KEEP does_not_exist_field -| EVAL does_not_exist_field = 42 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected deleted file mode 100644 index 3532a4c9c1d48..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_LookupJoin[LEFT,[language_code{r}#0],[language_code{f()}#1],false,null] - |_Eval[[TOINTEGER(does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#2) AS language_code#0]] - | \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#2] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}#1, language_name{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql deleted file mode 100644 index 45bedb56b16b8..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoin/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| EVAL language_code = does_not_exist :: INTEGER -| LOOKUP JOIN languages_lookup ON language_code diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected deleted file mode 100644 index e3fe21e3dfcb0..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/analysis.expected +++ /dev/null @@ -1,6 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Filter[TOLONG(does_not_exist{f}#0) > 0[INTEGER]] - \_LookupJoin[LEFT,[language_code{r}#1],[language_code{f()}#2],false,null] - |_Eval[[languages{f()}#3 AS language_code#1]] - | \_EsRelation[employees][avg_worked_seconds{f}#4, birth_date{f}#5, emp_no{f}#6, first_name{f}#7, gender{f}#8, height{f}#9, height.float{f}#10, height.half_float{f}#11, height.scaled_float{f}#12, hire_date{f}#13, is_rehired{f}#14, job_positions{f}#15, languages{f}#3, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f}#0] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}#2, language_name{f}#26] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql deleted file mode 100644 index face9633033a7..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testLookupJoinWithFilter/load/query.esql +++ /dev/null @@ -1,4 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| EVAL language_code = languages -| LOOKUP JOIN languages_lookup ON language_code -| WHERE does_not_exist::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected deleted file mode 100644 index f239763e796e7..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[TODOUBLE(does_not_exist{f}#0) + 1[INTEGER] AS x#1]] - \_Project[[avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4 AS employee_number#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#0]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/query.esql deleted file mode 100644 index 15a3d0131d523..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| RENAME emp_no AS employee_number -| EVAL x = does_not_exist::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected deleted file mode 100644 index f96459400cd9a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/analysis.expected +++ /dev/null @@ -1,5 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Eval[[TODOUBLE(does_not_exist{r}#0) + 1[INTEGER] AS x#1]] - \_Project[[avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4 AS employee_number#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist{r}#0]] - \_Eval[[null[NULL] AS does_not_exist#0]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql deleted file mode 100644 index 7475a95153a3a..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRenameEval/nullify/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| RENAME emp_no AS employee_number -| EVAL x = does_not_exist::DOUBLE + 1 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRow/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRow/load/query.esql deleted file mode 100644 index a37a2ef472baa..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testRow/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; ROW x = 1 -| EVAL y = does_not_exist_field1::INTEGER + x -| KEEP *, does_not_exist_field2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/analysis.expected deleted file mode 100644 index 97a29a5f794e0..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{f}#0) > 0[INTEGER]] AS c#1]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24, does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/query.esql deleted file mode 100644 index c761b990a28aa..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/analysis.expected deleted file mode 100644 index 31ed40e729ba7..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/analysis.expected +++ /dev/null @@ -1,4 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[],[FilteredExpression[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]),TOLONG(does_not_exist1{r}#0) > 0[INTEGER]] AS c#1]] - \_Eval[[null[NULL] AS does_not_exist1#0]] - \_EsRelation[employees][avg_worked_seconds{f}#2, birth_date{f}#3, emp_no{f}#4, first_name{f}#5, gender{f}#6, height{f}#7, height.float{f}#8, height.half_float{f}#9, height.scaled_float{f}#10, hire_date{f}#11, is_rehired{f}#12, job_positions{f}#13, languages{f}#14, languages.byte{f}#15, languages.long{f}#16, languages.short{f}#17, last_name{f}#18, salary{f}#19, salary_change{f}#20, salary_change.int{f}#21, salary_change.keyword{f}#22, salary_change.long{f}#23, still_hired{f}#24] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/query.esql deleted file mode 100644 index 7c028cc985242..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testStatsAggFiltering/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| STATS c = COUNT(*) WHERE does_not_exist1::LONG > 0 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected deleted file mode 100644 index 50d5fdfd9af0d..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/analysis.expected +++ /dev/null @@ -1,11 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[emp_no{r}#0, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] - \_UnionAll[[avg_worked_seconds{r}#4, birth_date{r}#5, emp_no{r}#0, first_name{r}#6, gender{r}#7, height{r}#8, height.float{r}#9, height.half_float{r}#10, height.scaled_float{r}#11, hire_date{r}#12, is_rehired{r}#13, job_positions{r}#14, languages{r}#15, languages.byte{r}#16, languages.long{r}#17, languages.short{r}#18, last_name{r}#19, salary{r}#20, salary_change{r}#21, salary_change.int{r}#22, salary_change.keyword{r}#23, salary_change.long{r}#24, still_hired{r}#25, language_code{r}#1, unmapped1{r}#2, unmapped2{r}#3]] - |_Project[[avg_worked_seconds{f()}#26, birth_date{f()}#27, emp_no{f()}#28, first_name{f()}#29, gender{f()}#30, height{f()}#31, height.float{f()}#32, height.half_float{f()}#33, height.scaled_float{f()}#34, hire_date{f()}#35, is_rehired{f()}#36, job_positions{f()}#37, languages{f()}#38, languages.byte{f()}#39, languages.long{f()}#40, languages.short{f()}#41, last_name{f()}#42, salary{f()}#43, salary_change{f()}#44, salary_change.int{f()}#45, salary_change.keyword{f()}#46, salary_change.long{f()}#47, still_hired{f()}#48, language_code{r}#49, unmapped1{r}#50, unmapped2{r}#51]] - | \_Eval[[null[INTEGER] AS language_code#49, null[KEYWORD] AS unmapped1#50, null[KEYWORD] AS unmapped2#51]] - | \_EsRelation[employees][avg_worked_seconds{f}#26, birth_date{f}#27, emp_no{f}#28, first_name{f}#29, gender{f}#30, height{f}#31, height.float{f}#32, height.half_float{f}#33, height.scaled_float{f}#34, hire_date{f}#35, is_rehired{f}#36, job_positions{f}#37, languages{f}#38, languages.byte{f}#39, languages.long{f}#40, languages.short{f}#41, last_name{f}#42, salary{f}#43, salary_change{f}#44, salary_change.int{f}#45, salary_change.keyword{f}#46, salary_change.long{f}#47, still_hired{f}#48] - \_Project[[avg_worked_seconds{r}#52, birth_date{r}#53, emp_no{r}#54, first_name{r}#55, gender{r}#56, height{r}#57, height.float{r}#58, height.half_float{r}#59, height.scaled_float{r}#60, hire_date{r}#61, is_rehired{r}#62, job_positions{r}#63, languages{r}#64, languages.byte{r}#65, languages.long{r}#66, languages.short{r}#67, last_name{r}#68, salary{r}#69, salary_change{r}#70, salary_change.int{r}#71, salary_change.keyword{r}#72, salary_change.long{r}#73, still_hired{r}#74, language_code{f()}#75, unmapped1{f(PotentiallyUnmappedKeywordEsField)}#76, unmapped2{f(PotentiallyUnmappedKeywordEsField)}#77]] - \_Eval[[null[LONG] AS avg_worked_seconds#52, null[DATETIME] AS birth_date#53, null[INTEGER] AS emp_no#54, null[KEYWORD] AS first_name#55, null[KEYWORD] AS gender#56, null[DOUBLE] AS height#57, null[DOUBLE] AS height.float#58, null[DOUBLE] AS height.half_float#59, null[DOUBLE] AS height.scaled_float#60, null[DATETIME] AS hire_date#61, null[BOOLEAN] AS is_rehired#62, null[KEYWORD] AS job_positions#63, null[INTEGER] AS languages#64, null[INTEGER] AS languages.byte#65, null[LONG] AS languages.long#66, null[INTEGER] AS languages.short#67, null[KEYWORD] AS last_name#68, null[INTEGER] AS salary#69, null[DOUBLE] AS salary_change#70, null[INTEGER] AS salary_change.int#71, null[KEYWORD] AS salary_change.keyword#72, null[LONG] AS salary_change.long#73, null[BOOLEAN] AS still_hired#74]] - \_Subquery[] - \_Project[[language_code{f()}#75, unmapped1{f(PotentiallyUnmappedKeywordEsField)}#76, unmapped2{f(PotentiallyUnmappedKeywordEsField)}#77]] - \_EsRelation[languages][language_code{f}#75, language_name{f}#78, unmapped1{f}#76, unmapped2{f}#77] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql deleted file mode 100644 index f48daedc4ab1d..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepMultipleUnmapped/load/query.esql +++ /dev/null @@ -1,3 +0,0 @@ -SET unmapped_fields="load"; FROM employees, - (FROM languages | KEEP language_code, unmapped1, unmapped2) -| KEEP emp_no, language_code, unmapped1, unmapped2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected deleted file mode 100644 index 113ceff5421e3..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/analysis.expected +++ /dev/null @@ -1,13 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[emp_no{r}#0, language_code{r}#1, does_not_exist{r}#2]] - \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, language_code{r}#1, does_not_exist{r}#2]] - |_Project[[avg_worked_seconds{f()}#25, birth_date{f()}#26, emp_no{f()}#27, first_name{f()}#28, gender{f()}#29, height{f()}#30, height.float{f()}#31, height.half_float{f()}#32, height.scaled_float{f()}#33, hire_date{f()}#34, is_rehired{f()}#35, job_positions{f()}#36, languages{f()}#37, languages.byte{f()}#38, languages.long{f()}#39, languages.short{f()}#40, last_name{f()}#41, salary{f()}#42, salary_change{f()}#43, salary_change.int{f()}#44, salary_change.keyword{f()}#45, salary_change.long{f()}#46, still_hired{f()}#47, language_code{r}#48, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#49]] - | \_Eval[[null[INTEGER] AS language_code#48]] - | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47, does_not_exist{f}#49] - \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f()}#73, does_not_exist{r}#74]] - \_Eval[[null[KEYWORD] AS does_not_exist#74]] - \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, language_code{f()}#73]] - \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] - \_Subquery[] - \_Project[[language_code{f()}#73]] - \_EsRelation[languages][language_code{f}#73, language_name{f}#75, does_not_exist{f}#76] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql deleted file mode 100644 index 1b76ece4d7ba5..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryKeepUnmapped/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees, (FROM languages | KEEP language_code) -| KEEP emp_no, language_code, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected deleted file mode 100644 index 7c4f1036413c8..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/analysis.expected +++ /dev/null @@ -1,11 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Project[[emp_no{r}#0, max_ts{r}#1, does_not_exist{r}#2]] - \_UnionAll[[avg_worked_seconds{r}#3, birth_date{r}#4, emp_no{r}#0, first_name{r}#5, gender{r}#6, height{r}#7, height.float{r}#8, height.half_float{r}#9, height.scaled_float{r}#10, hire_date{r}#11, is_rehired{r}#12, job_positions{r}#13, languages{r}#14, languages.byte{r}#15, languages.long{r}#16, languages.short{r}#17, last_name{r}#18, salary{r}#19, salary_change{r}#20, salary_change.int{r}#21, salary_change.keyword{r}#22, salary_change.long{r}#23, still_hired{r}#24, max_ts{r}#1, does_not_exist{r}#2]] - |_Project[[avg_worked_seconds{f()}#25, birth_date{f()}#26, emp_no{f()}#27, first_name{f()}#28, gender{f()}#29, height{f()}#30, height.float{f()}#31, height.half_float{f()}#32, height.scaled_float{f()}#33, hire_date{f()}#34, is_rehired{f()}#35, job_positions{f()}#36, languages{f()}#37, languages.byte{f()}#38, languages.long{f()}#39, languages.short{f()}#40, last_name{f()}#41, salary{f()}#42, salary_change{f()}#43, salary_change.int{f()}#44, salary_change.keyword{f()}#45, salary_change.long{f()}#46, still_hired{f()}#47, max_ts{r}#48, does_not_exist{r}#49]] - | \_Eval[[null[DATETIME] AS max_ts#48, null[KEYWORD] AS does_not_exist#49]] - | \_EsRelation[employees][avg_worked_seconds{f}#25, birth_date{f}#26, emp_no{f}#27, first_name{f}#28, gender{f}#29, height{f}#30, height.float{f}#31, height.half_float{f}#32, height.scaled_float{f}#33, hire_date{f}#34, is_rehired{f}#35, job_positions{f}#36, languages{f}#37, languages.byte{f}#38, languages.long{f}#39, languages.short{f}#40, last_name{f}#41, salary{f}#42, salary_change{f}#43, salary_change.int{f}#44, salary_change.keyword{f}#45, salary_change.long{f}#46, still_hired{f}#47] - \_Project[[avg_worked_seconds{r}#50, birth_date{r}#51, emp_no{r}#52, first_name{r}#53, gender{r}#54, height{r}#55, height.float{r}#56, height.half_float{r}#57, height.scaled_float{r}#58, hire_date{r}#59, is_rehired{r}#60, job_positions{r}#61, languages{r}#62, languages.byte{r}#63, languages.long{r}#64, languages.short{r}#65, last_name{r}#66, salary{r}#67, salary_change{r}#68, salary_change.int{r}#69, salary_change.keyword{r}#70, salary_change.long{r}#71, still_hired{r}#72, max_ts{r}#73, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74]] - \_Eval[[null[LONG] AS avg_worked_seconds#50, null[DATETIME] AS birth_date#51, null[INTEGER] AS emp_no#52, null[KEYWORD] AS first_name#53, null[KEYWORD] AS gender#54, null[DOUBLE] AS height#55, null[DOUBLE] AS height.float#56, null[DOUBLE] AS height.half_float#57, null[DOUBLE] AS height.scaled_float#58, null[DATETIME] AS hire_date#59, null[BOOLEAN] AS is_rehired#60, null[KEYWORD] AS job_positions#61, null[INTEGER] AS languages#62, null[INTEGER] AS languages.byte#63, null[LONG] AS languages.long#64, null[INTEGER] AS languages.short#65, null[KEYWORD] AS last_name#66, null[INTEGER] AS salary#67, null[DOUBLE] AS salary_change#68, null[INTEGER] AS salary_change.int#69, null[KEYWORD] AS salary_change.keyword#70, null[LONG] AS salary_change.long#71, null[BOOLEAN] AS still_hired#72]] - \_Subquery[] - \_Aggregate[[does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74],[MAX(@timestamp{f()}#75,true[BOOLEAN],PT0S[TIME_DURATION]) AS max_ts#73, does_not_exist{f(PotentiallyUnmappedKeywordEsField)}#74]] - \_EsRelation[sample_data][@timestamp{f}#75, client_ip{f}#76, event_duration{f}#77, message{f}#78, does_not_exist{f}#74] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql deleted file mode 100644 index dabf6fc1b0e8c..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubqueryWithStats/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees, (FROM sample_data | STATS max_ts = MAX(@timestamp) BY does_not_exist) -| KEEP emp_no, max_ts, does_not_exist diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/analysis.expected deleted file mode 100644 index 31dea66259d69..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/analysis.expected +++ /dev/null @@ -1,35 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_MvExpand[languageCode{r}#0,languageCode{r}#1] - \_Project[[count(*){r}#2, emp_no{r}#3 AS empNo#4, language_code{r}#5 AS languageCode#0, does_not_exist2{r}#6]] - \_Aggregate[[emp_no{r}#3, language_code{r}#5, does_not_exist2{r}#6],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#2, emp_no{r}#3, language_code{r}#5, does_not_exist2{r}#6]] - \_Filter[emp_no{r}#3 > 10000[INTEGER] OR $$does_not_exist1$converted_to$long{r$}#7 < 10[INTEGER]] - \_UnionAll[[avg_worked_seconds{r}#8, birth_date{r}#9, emp_no{r}#3, first_name{r}#10, gender{r}#11, height{r}#12, height.float{r}#13, height.half_float{r}#14, height.scaled_float{r}#15, hire_date{r}#16, is_rehired{r}#17, job_positions{r}#18, languages{r}#19, languages.byte{r}#20, languages.long{r}#21, languages.short{r}#22, last_name{r}#23, salary{r}#24, salary_change{r}#25, salary_change.int{r}#26, salary_change.keyword{r}#27, salary_change.long{r}#28, still_hired{r}#29, language_code{r}#5, languageName{r}#30, max(@timestamp){r}#31, language_name{r}#32, does_not_exist1{r}#33, $$does_not_exist1$converted_to$long{r$}#7, does_not_exist2{r}#6]] - |_Project[[avg_worked_seconds{f}#34, birth_date{f}#35, emp_no{f}#36, first_name{f}#37, gender{f}#38, height{f}#39, height.float{f}#40, height.half_float{f}#41, height.scaled_float{f}#42, hire_date{f}#43, is_rehired{f}#44, job_positions{f}#45, languages{f}#46, languages.byte{f}#47, languages.long{f}#48, languages.short{f}#49, last_name{f}#50, salary{f}#51, salary_change{f}#52, salary_change.int{f}#53, salary_change.keyword{f}#54, salary_change.long{f}#55, still_hired{f}#56, language_code{r}#57, languageName{r}#58, max(@timestamp){r}#59, language_name{r}#60, does_not_exist1{f}#61, $$does_not_exist1$converted_to$long{r$}#62, does_not_exist2{f}#63]] - | \_Eval[[TOLONG(does_not_exist1{f}#61) AS $$does_not_exist1$converted_to$long#62]] - | \_Eval[[null[INTEGER] AS language_code#57, null[KEYWORD] AS languageName#58, null[DATETIME] AS max(@timestamp)#59, null[KEYWORD] AS language_name#60]] - | \_EsRelation[employees][avg_worked_seconds{f}#34, birth_date{f}#35, emp_no{f}#36, first_name{f}#37, gender{f}#38, height{f}#39, height.float{f}#40, height.half_float{f}#41, height.scaled_float{f}#42, hire_date{f}#43, is_rehired{f}#44, job_positions{f}#45, languages{f}#46, languages.byte{f}#47, languages.long{f}#48, languages.short{f}#49, last_name{f}#50, salary{f}#51, salary_change{f}#52, salary_change.int{f}#53, salary_change.keyword{f}#54, salary_change.long{f}#55, still_hired{f}#56, does_not_exist1{f}#61, does_not_exist2{f}#63] - |_Project[[avg_worked_seconds{r}#64, birth_date{r}#65, emp_no{r}#66, first_name{r}#67, gender{r}#68, height{r}#69, height.float{r}#70, height.half_float{r}#71, height.scaled_float{r}#72, hire_date{r}#73, is_rehired{r}#74, job_positions{r}#75, languages{r}#76, languages.byte{r}#77, languages.long{r}#78, languages.short{r}#79, last_name{r}#80, salary{r}#81, salary_change{r}#82, salary_change.int{r}#83, salary_change.keyword{r}#84, salary_change.long{r}#85, still_hired{r}#86, language_code{f}#87, languageName{r}#88, max(@timestamp){r}#89, language_name{r}#90, does_not_exist1{f}#91, $$does_not_exist1$converted_to$long{r$}#92, does_not_exist2{f}#93]] - | \_Eval[[TOLONG(does_not_exist1{f}#91) AS $$does_not_exist1$converted_to$long#92]] - | \_Eval[[null[LONG] AS avg_worked_seconds#64, null[DATETIME] AS birth_date#65, null[INTEGER] AS emp_no#66, null[KEYWORD] AS first_name#67, null[KEYWORD] AS gender#68, null[DOUBLE] AS height#69, null[DOUBLE] AS height.float#70, null[DOUBLE] AS height.half_float#71, null[DOUBLE] AS height.scaled_float#72, null[DATETIME] AS hire_date#73, null[BOOLEAN] AS is_rehired#74, null[KEYWORD] AS job_positions#75, null[INTEGER] AS languages#76, null[INTEGER] AS languages.byte#77, null[LONG] AS languages.long#78, null[INTEGER] AS languages.short#79, null[KEYWORD] AS last_name#80, null[INTEGER] AS salary#81, null[DOUBLE] AS salary_change#82, null[INTEGER] AS salary_change.int#83, null[KEYWORD] AS salary_change.keyword#84, null[LONG] AS salary_change.long#85, null[BOOLEAN] AS still_hired#86, null[DATETIME] AS max(@timestamp)#89, null[KEYWORD] AS language_name#90]] - | \_Subquery[] - | \_Project[[language_code{f}#87, language_name{f}#94 AS languageName#88, does_not_exist1{f}#91, does_not_exist2{f}#93]] - | \_Filter[language_code{f}#87 > 10[INTEGER]] - | \_EsRelation[languages][language_code{f}#87, language_name{f}#94, does_not_exist1{f}#91, does_not_exist2{f}#93] - |_Project[[avg_worked_seconds{r}#95, birth_date{r}#96, emp_no{r}#97, first_name{r}#98, gender{r}#99, height{r}#100, height.float{r}#101, height.half_float{r}#102, height.scaled_float{r}#103, hire_date{r}#104, is_rehired{r}#105, job_positions{r}#106, languages{r}#107, languages.byte{r}#108, languages.long{r}#109, languages.short{r}#110, last_name{r}#111, salary{r}#112, salary_change{r}#113, salary_change.int{r}#114, salary_change.keyword{r}#115, salary_change.long{r}#116, still_hired{r}#117, language_code{r}#118, languageName{r}#119, max(@timestamp){r}#120, language_name{r}#121, does_not_exist1{r}#122, $$does_not_exist1$converted_to$long{r$}#123, does_not_exist2{r}#124]] - | \_Eval[[null[NULL] AS does_not_exist2#124]] - | \_Project[[avg_worked_seconds{r}#95, birth_date{r}#96, emp_no{r}#97, first_name{r}#98, gender{r}#99, height{r}#100, height.float{r}#101, height.half_float{r}#102, height.scaled_float{r}#103, hire_date{r}#104, is_rehired{r}#105, job_positions{r}#106, languages{r}#107, languages.byte{r}#108, languages.long{r}#109, languages.short{r}#110, last_name{r}#111, salary{r}#112, salary_change{r}#113, salary_change.int{r}#114, salary_change.keyword{r}#115, salary_change.long{r}#116, still_hired{r}#117, language_code{r}#118, languageName{r}#119, max(@timestamp){r}#120, language_name{r}#121, does_not_exist1{r}#122, $$does_not_exist1$converted_to$long{r$}#123]] - | \_Eval[[TOLONG(does_not_exist1{r}#122) AS $$does_not_exist1$converted_to$long#123]] - | \_Eval[[null[NULL] AS does_not_exist1#122]] - | \_Project[[avg_worked_seconds{r}#95, birth_date{r}#96, emp_no{r}#97, first_name{r}#98, gender{r}#99, height{r}#100, height.float{r}#101, height.half_float{r}#102, height.scaled_float{r}#103, hire_date{r}#104, is_rehired{r}#105, job_positions{r}#106, languages{r}#107, languages.byte{r}#108, languages.long{r}#109, languages.short{r}#110, last_name{r}#111, salary{r}#112, salary_change{r}#113, salary_change.int{r}#114, salary_change.keyword{r}#115, salary_change.long{r}#116, still_hired{r}#117, language_code{r}#118, languageName{r}#119, max(@timestamp){r}#120, language_name{r}#121]] - | \_Eval[[null[LONG] AS avg_worked_seconds#95, null[DATETIME] AS birth_date#96, null[INTEGER] AS emp_no#97, null[KEYWORD] AS first_name#98, null[KEYWORD] AS gender#99, null[DOUBLE] AS height#100, null[DOUBLE] AS height.float#101, null[DOUBLE] AS height.half_float#102, null[DOUBLE] AS height.scaled_float#103, null[DATETIME] AS hire_date#104, null[BOOLEAN] AS is_rehired#105, null[KEYWORD] AS job_positions#106, null[INTEGER] AS languages#107, null[INTEGER] AS languages.byte#108, null[LONG] AS languages.long#109, null[INTEGER] AS languages.short#110, null[KEYWORD] AS last_name#111, null[INTEGER] AS salary#112, null[DOUBLE] AS salary_change#113, null[INTEGER] AS salary_change.int#114, null[KEYWORD] AS salary_change.keyword#115, null[LONG] AS salary_change.long#116, null[BOOLEAN] AS still_hired#117, null[INTEGER] AS language_code#118, null[KEYWORD] AS languageName#119, null[KEYWORD] AS language_name#121]] - | \_Subquery[] - | \_Aggregate[[],[MAX(@timestamp{f}#125,true[BOOLEAN],PT0S[TIME_DURATION]) AS max(@timestamp)#120]] - | \_EsRelation[sample_data][@timestamp{f}#125, client_ip{f}#126, event_duration{f}#127, message{f}#128, does_not_exist1{f}#129, does_not_exist2{f}#130] - \_Project[[avg_worked_seconds{f}#131, birth_date{f}#132, emp_no{f}#133, first_name{f}#134, gender{f}#135, height{f}#136, height.float{f}#137, height.half_float{f}#138, height.scaled_float{f}#139, hire_date{f}#140, is_rehired{f}#141, job_positions{f}#142, languages{f}#143, languages.byte{f}#144, languages.long{f}#145, languages.short{f}#146, last_name{f}#147, salary{f}#148, salary_change{f}#149, salary_change.int{f}#150, salary_change.keyword{f}#151, salary_change.long{f}#152, still_hired{f}#153, language_code{r}#154, languageName{r}#155, max(@timestamp){r}#156, language_name{f}#157, does_not_exist1{f}#158, $$does_not_exist1$converted_to$long{r$}#159, does_not_exist2{f}#160]] - \_Eval[[TOLONG(does_not_exist1{f}#158) AS $$does_not_exist1$converted_to$long#159]] - \_Eval[[null[KEYWORD] AS languageName#155, null[DATETIME] AS max(@timestamp)#156]] - \_Subquery[] - \_LookupJoin[LEFT,[language_code{r}#154],[language_code{f}#161],false,null] - |_Eval[[languages{f}#143 AS language_code#154]] - | \_EsRelation[employees][avg_worked_seconds{f}#131, birth_date{f}#132, emp_no{f}#133, first_name{f}#134, gender{f}#135, height{f}#136, height.float{f}#137, height.half_float{f}#138, height.scaled_float{f}#139, hire_date{f}#140, is_rehired{f}#141, job_positions{f}#142, languages{f}#143, languages.byte{f}#144, languages.long{f}#145, languages.short{f}#146, last_name{f}#147, salary{f}#148, salary_change{f}#149, salary_change.int{f}#150, salary_change.keyword{f}#151, salary_change.long{f}#152, still_hired{f}#153, does_not_exist1{f}#158, does_not_exist2{f}#160] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}#161, language_name{f}#157] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/query.esql deleted file mode 100644 index 17e10ed04b0eb..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/query.esql +++ /dev/null @@ -1,13 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees, - (FROM languages - | WHERE language_code > 10 - | RENAME language_name as languageName), - (FROM sample_data - | STATS max(@timestamp)), - (FROM employees - | EVAL language_code = languages - | LOOKUP JOIN languages_lookup ON language_code) -| WHERE emp_no > 10000 OR does_not_exist1::LONG < 10 -| STATS count(*) BY emp_no, language_code, does_not_exist2 -| RENAME emp_no AS empNo, language_code AS languageCode -| MV_EXPAND languageCode From 25d13c3eb4d0ab3ec047e36e9ca73f0511c73c0d Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 16 Mar 2026 14:20:16 +0200 Subject: [PATCH 100/137] Undelete and add golden --- .../xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java | 7 +++++++ .../testInlineStatsAggAndGroup/load/analysis.expected | 4 ++++ .../testInlineStatsAggAndGroup/load/query.esql | 2 ++ .../testInlineStatsAggAndGroup/nullify/analysis.expected | 4 ++++ .../testInlineStatsAggAndGroup/nullify/query.esql | 2 ++ 5 files changed, 19 insertions(+) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/nullify/query.esql diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java index e3faf11ef4b5d..fff2f3542c18d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -183,6 +183,13 @@ public void testStatsAggAndGroup() throws Exception { """); } + public void testInlineStatsAggAndGroup() throws Exception { + runTests(""" + FROM employees + | INLINE STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 + """); + } + public void testStatsAggAndAliasedGroup() throws Exception { runTests(""" FROM employees diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/load/analysis.expected new file mode 100644 index 0000000000000..2852dfa549f3f --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_InlineStats[] + \_Aggregate[[does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0],[SUM(TODOUBLE(does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#1),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#2, does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0, does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/load/query.esql new file mode 100644 index 0000000000000..c7a26eebdd303 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/load/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="load"; FROM employees +| INLINE STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/nullify/analysis.expected new file mode 100644 index 0000000000000..853a6d68f1b57 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_InlineStats[] + \_Aggregate[[does_not_exist2{f}#0],[SUM(TODOUBLE(does_not_exist1{f}#1),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#2, does_not_exist2{f}#0]] + \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist2{f}#0, does_not_exist1{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/nullify/query.esql new file mode 100644 index 0000000000000..07f48b0742808 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStatsAggAndGroup/nullify/query.esql @@ -0,0 +1,2 @@ +SET unmapped_fields="nullify"; FROM employees +| INLINE STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 From 018b7797111e970d41c6f92f2967989e3f336b89 Mon Sep 17 00:00:00 2001 From: Mark Vieira Date: Sun, 15 Mar 2026 08:28:59 -0700 Subject: [PATCH 101/137] Native cli launcher (#143712) --- .../internal/docker/DockerBuildTask.java | 26 +- .../internal/docker/DockerSupportPlugin.java | 2 +- .../internal/docker/DockerSupportService.java | 44 +- .../internal/docker/NativeImageBuildTask.java | 209 ++++++++ .../elasticsearch/gradle/Architecture.java | 21 + distribution/build.gradle | 21 +- distribution/docker/build.gradle | 12 - distribution/src/bin/elasticsearch | 24 +- distribution/src/bin/elasticsearch.bat | 17 +- .../launcher/CliToolLauncher.java | 26 +- .../launcher/RedirectedStdoutTerminal.java | 52 ++ .../launcher/CliToolLauncherTests.java | 103 ++++ .../launcher/RedirectTestCliToolProvider.java | 29 ++ .../launcher/RedirectTestCommand.java | 46 ++ .../org.elasticsearch.cli.CliToolProvider | 1 + distribution/tools/server-cli/build.gradle | 1 + .../JvmArgumentParsingSystemMemoryInfo.java | 38 -- .../server/cli/JvmOptionsParser.java | 5 +- .../server/cli/OverheadSystemMemoryInfo.java | 35 -- .../cli/OverridableSystemMemoryInfo.java | 22 +- .../elasticsearch/server/cli/ServerCli.java | 137 +++--- .../server/cli/ServerProcessBuilder.java | 234 --------- .../cli/OverheadSystemMemoryInfoTests.java | 86 ---- .../cli/OverridableSystemMemoryInfoTests.java | 2 +- .../server/cli/ServerCliTests.java | 157 +----- .../server/cli/ServerProcessTests.java | 448 ------------------ .../tools/server-launcher/build.gradle | 64 +++ .../server/launcher}/ErrorPumpThread.java | 63 ++- .../server/launcher/ServerLauncher.java | 331 +++++++++++++ .../server/launcher}/ServerProcess.java | 53 +-- .../server/launcher/ErrorPumpThreadTests.java | 132 ++++++ .../server/launcher/ServerLauncherTests.java | 447 +++++++++++++++++ .../tools/windows-service-cli/build.gradle | 2 + .../windows/service/WindowsServiceDaemon.java | 122 ++++- .../service/WindowsServiceInstallCommand.java | 2 +- .../WindowsServiceInstallCommandTests.java | 2 +- libs/server-launcher-common/build.gradle | 25 + .../launcher/common/LaunchDescriptor.java | 311 ++++++++++++ .../server/launcher/common}/ProcessUtil.java | 17 +- .../common/LaunchDescriptorTests.java | 119 +++++ .../packaging/test/ArchiveTests.java | 6 +- .../packaging/test/DockerTests.java | 12 +- .../test/KeystoreManagementTests.java | 2 +- .../packaging/test/PackageTests.java | 4 +- .../packaging/util/Archives.java | 7 + settings.gradle | 1 + 46 files changed, 2334 insertions(+), 1186 deletions(-) create mode 100644 build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/NativeImageBuildTask.java create mode 100644 distribution/tools/cli-launcher/src/main/java/org/elasticsearch/launcher/RedirectedStdoutTerminal.java create mode 100644 distribution/tools/cli-launcher/src/test/java/org/elasticsearch/launcher/RedirectTestCliToolProvider.java create mode 100644 distribution/tools/cli-launcher/src/test/java/org/elasticsearch/launcher/RedirectTestCommand.java create mode 100644 distribution/tools/cli-launcher/src/test/resources/META-INF/services/org.elasticsearch.cli.CliToolProvider delete mode 100644 distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmArgumentParsingSystemMemoryInfo.java delete mode 100644 distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/OverheadSystemMemoryInfo.java delete mode 100644 distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ServerProcessBuilder.java delete mode 100644 distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/OverheadSystemMemoryInfoTests.java delete mode 100644 distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/ServerProcessTests.java create mode 100644 distribution/tools/server-launcher/build.gradle rename distribution/tools/{server-cli/src/main/java/org/elasticsearch/server/cli => server-launcher/src/main/java/org/elasticsearch/server/launcher}/ErrorPumpThread.java (57%) create mode 100644 distribution/tools/server-launcher/src/main/java/org/elasticsearch/server/launcher/ServerLauncher.java rename distribution/tools/{server-cli/src/main/java/org/elasticsearch/server/cli => server-launcher/src/main/java/org/elasticsearch/server/launcher}/ServerProcess.java (54%) create mode 100644 distribution/tools/server-launcher/src/test/java/org/elasticsearch/server/launcher/ErrorPumpThreadTests.java create mode 100644 distribution/tools/server-launcher/src/test/java/org/elasticsearch/server/launcher/ServerLauncherTests.java create mode 100644 libs/server-launcher-common/build.gradle create mode 100644 libs/server-launcher-common/src/main/java/org/elasticsearch/server/launcher/common/LaunchDescriptor.java rename {distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli => libs/server-launcher-common/src/main/java/org/elasticsearch/server/launcher/common}/ProcessUtil.java (69%) create mode 100644 libs/server-launcher-common/src/test/java/org/elasticsearch/server/launcher/common/LaunchDescriptorTests.java diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/DockerBuildTask.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/DockerBuildTask.java index 87d7d8d8ed47c..e4314b9dcfaef 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/DockerBuildTask.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/DockerBuildTask.java @@ -22,6 +22,7 @@ import org.gradle.api.provider.MapProperty; import org.gradle.api.provider.Property; import org.gradle.api.provider.SetProperty; +import org.gradle.api.services.ServiceReference; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.InputDirectory; import org.gradle.api.tasks.Optional; @@ -39,6 +40,7 @@ import java.io.IOException; import java.nio.file.Files; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -68,10 +70,20 @@ public DockerBuildTask(WorkerExecutor workerExecutor, ObjectFactory objectFactor this.dockerContext = objectFactory.directoryProperty(); this.buildArgs = objectFactory.mapProperty(String.class, String.class); this.markerFile.set(projectLayout.getBuildDirectory().file("markers/" + this.getName() + ".marker")); + onlyIf("Docker supports all requested platforms", task -> { + var platforms = getPlatforms().getOrElse(Collections.emptySet()); + if (platforms.isEmpty()) { + return false; + } + DockerSupportService support = getDockerSupport().get(); + return platforms.stream() + .allMatch(platform -> Architecture.fromDockerPlatform(platform).map(support::isArchitectureSupported).orElse(false)); + }); } @TaskAction public void build() { + String dockerExecutable = getDockerSupport().get().getResolvedDockerExecutable(); workerExecutor.noIsolation().submit(DockerBuildAction.class, params -> { params.getDockerContext().set(dockerContext); params.getMarkerFile().set(markerFile); @@ -82,6 +94,7 @@ public void build() { params.getBaseImages().set(Arrays.asList(baseImages)); params.getBuildArgs().set(buildArgs); params.getPlatforms().set(getPlatforms()); + params.getDockerExecutable().set(dockerExecutable); }); } @@ -148,6 +161,9 @@ public RegularFileProperty getMarkerFile() { return markerFile; } + @ServiceReference(DockerSupportPlugin.DOCKER_SUPPORT_SERVICE_NAME) + public abstract Property getDockerSupport(); + public abstract static class DockerBuildAction implements WorkAction { private final ExecOperations execOperations; @@ -163,12 +179,13 @@ public DockerBuildAction(ExecOperations execOperations) { */ private void pullBaseImage(String baseImage) { final int maxAttempts = 10; + String docker = getParameters().getDockerExecutable().get(); for (int attempt = 1; attempt <= maxAttempts; attempt++) { try { LoggedExec.exec(execOperations, spec -> { maybeConfigureDockerConfig(spec); - spec.executable("docker"); + spec.executable(docker); spec.args("pull"); spec.environment("DOCKER_BUILDKIT", "1"); spec.args(baseImage); @@ -205,7 +222,7 @@ public void execute() { LoggedExec.exec(execOperations, spec -> { maybeConfigureDockerConfig(spec); - spec.executable("docker"); + spec.executable(parameters.getDockerExecutable().get()); spec.environment("DOCKER_BUILDKIT", "1"); if (isCrossPlatform) { spec.args("buildx"); @@ -260,9 +277,10 @@ private boolean isCrossPlatform() { private String getImageChecksum(String imageTag) { final ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + String docker = getParameters().getDockerExecutable().get(); execOperations.exec(spec -> { - spec.setCommandLine("docker", "inspect", "--format", "{{ .Id }}", imageTag); + spec.setCommandLine(docker, "inspect", "--format", "{{ .Id }}", imageTag); spec.setStandardOutput(stdout); spec.setIgnoreExitValue(false); }); @@ -289,5 +307,7 @@ interface Parameters extends WorkParameters { SetProperty getPlatforms(); Property getPush(); + + Property getDockerExecutable(); } } diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/DockerSupportPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/DockerSupportPlugin.java index 7ec35ccd32e10..bf6165447fa9f 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/DockerSupportPlugin.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/DockerSupportPlugin.java @@ -43,7 +43,7 @@ public void apply(Project project) { params.getIsCI().set(buildParams.getCi()); })); - // Ensure that if we are trying to run any DockerBuildTask tasks, we assert an available Docker installation exists + // Ensure that if we are trying to run Docker build tasks, we assert an available Docker installation exists project.getGradle().getTaskGraph().whenReady(graph -> { List dockerTasks = graph.getAllTasks() .stream() diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/DockerSupportService.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/DockerSupportService.java index f40f5d932b701..8d13f11800c39 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/DockerSupportService.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/DockerSupportService.java @@ -49,8 +49,8 @@ public abstract class DockerSupportService implements BuildService { private static final Logger LOGGER = Logging.getLogger(DockerSupportService.class); - // Defines the possible locations of the Docker CLI. These will be searched in order. - private static final String[] DOCKER_BINARIES = { "/usr/bin/docker", "/usr/local/bin/docker" }; + // Defines the possible locations of the Docker CLI. Searched in order for resolution and availability. + private static final String[] DOCKER_BINARIES = { "/usr/local/bin/docker", "/usr/bin/docker", "/opt/homebrew/bin/docker" }; private static final String[] DOCKER_COMPOSE_BINARIES = { "/usr/local/bin/docker-compose", "/usr/bin/docker-compose", @@ -72,7 +72,7 @@ public DockerSupportService(ProviderFactory providerFactory) { * * @return the results of the search. */ - public DockerAvailability getDockerAvailability() { + public synchronized DockerAvailability getDockerAvailability() { if (this.dockerAvailability == null) { String dockerPath; String dockerComposePath = null; @@ -305,15 +305,43 @@ static Map parseOsRelease(final List osReleaseLines) { } /** - * Searches the entries in {@link #DOCKER_BINARIES} for the Docker CLI. This method does - * not check whether the Docker installation appears usable, see {@link #getDockerAvailability()} - * instead. + * Resolves the Docker executable so it can be found even when PATH is minimal (e.g. Gradle + * workers or IDE). Searches PATH first for an executable named "docker", then falls back to + * {@link #DOCKER_BINARIES}. Use this when invoking docker from tasks so the binary is found + * regardless of worker environment. + * + * @return the absolute path to the Docker CLI if found and executable, otherwise "docker". + */ + public String getResolvedDockerExecutable() { + String pathEnv = System.getenv("PATH"); + if (pathEnv != null && pathEnv.isEmpty() == false) { + String separator = System.getProperty("path.separator", ":"); + for (String dir : pathEnv.split(separator)) { + File candidate = new File(dir.trim(), "docker"); + if (candidate.isFile() && candidate.canExecute()) { + return candidate.getAbsolutePath(); + } + } + } + for (String path : DOCKER_BINARIES) { + File f = new File(path); + if (f.isFile() && f.canExecute()) { + return f.getAbsolutePath(); + } + } + return "docker"; + } + + /** + * Searches for the Docker CLI using the same logic as {@link #getResolvedDockerExecutable()}. + * This method does not check whether the Docker installation appears usable, see + * {@link #getDockerAvailability()} instead. * * @return the path to a CLI, if available. */ private Optional getDockerPath() { - // Check if the Docker binary exists - return Stream.of(DOCKER_BINARIES).filter(path -> new File(path).exists()).findFirst(); + String resolved = getResolvedDockerExecutable(); + return "docker".equals(resolved) ? Optional.empty() : Optional.of(resolved); } /** diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/NativeImageBuildTask.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/NativeImageBuildTask.java new file mode 100644 index 0000000000000..184933989ff8d --- /dev/null +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/NativeImageBuildTask.java @@ -0,0 +1,209 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ +package org.elasticsearch.gradle.internal.docker; + +import org.elasticsearch.gradle.Architecture; +import org.elasticsearch.gradle.LoggedExec; +import org.gradle.api.DefaultTask; +import org.gradle.api.GradleException; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.FileCollection; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.services.ServiceReference; +import org.gradle.api.tasks.CacheableTask; +import org.gradle.api.tasks.Classpath; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.Optional; +import org.gradle.api.tasks.OutputFile; +import org.gradle.api.tasks.TaskAction; +import org.gradle.process.ExecOperations; +import org.gradle.process.ExecSpec; +import org.gradle.workers.WorkAction; +import org.gradle.workers.WorkParameters; +import org.gradle.workers.WorkerExecutor; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import javax.inject.Inject; + +/** + * Builds a GraalVM native-image binary by running native-image inside a Docker + * container. Uses the Gradle worker API so multiple architecture builds can + * run in parallel, and is cacheable for remote build cache. + * + * We assume native images to be optional, and a fallback to be available, so + * this task will be skipped if Docker is not available or the target platform + * is not supported rather than failing. + */ +@CacheableTask +public abstract class NativeImageBuildTask extends DefaultTask { + + private FileCollection classpath; + + @Inject + public NativeImageBuildTask() { + onlyIf( + "Docker supports target platform", + task -> Architecture.fromDockerPlatform(getPlatform().getOrNull()) + .map(arch -> getDockerSupport().get().isArchitectureSupported(arch)) + .orElse(false) + && getDockerSupport().get().getDockerAvailability().isAvailable() + ); + } + + @Classpath + public FileCollection getClasspath() { + return classpath; + } + + public void setClasspath(FileCollection classpath) { + this.classpath = classpath; + } + + @Input + public abstract Property getImageTag(); + + @Input + public abstract Property getPlatform(); + + @Input + public abstract Property getMainClass(); + + /** + * When true, pass {@code --static} to native-image to produce a fully static binary. + * Defaults to false. + */ + @Input + @Optional + public abstract Property getStatic(); + + @OutputFile + public abstract RegularFileProperty getOutputFile(); + + @ServiceReference(DockerSupportPlugin.DOCKER_SUPPORT_SERVICE_NAME) + public abstract Property getDockerSupport(); + + @Inject + public abstract WorkerExecutor getWorkerExecutor(); + + @TaskAction + public void execute() { + String dockerExecutable = getDockerSupport().get().getResolvedDockerExecutable(); + getWorkerExecutor().noIsolation().submit(NativeImageBuildAction.class, params -> { + params.getClasspath().setFrom(getClasspath()); + params.getImageTag().set(getImageTag()); + params.getPlatform().set(getPlatform()); + params.getMainClass().set(getMainClass()); + params.getStatic().set(getStatic().getOrElse(false)); + params.getOutputFile().set(getOutputFile()); + params.getDockerExecutable().set(dockerExecutable); + }); + } + + interface Parameters extends WorkParameters { + ConfigurableFileCollection getClasspath(); + + Property getImageTag(); + + Property getPlatform(); + + Property getMainClass(); + + Property getStatic(); + + RegularFileProperty getOutputFile(); + + Property getDockerExecutable(); + } + + public abstract static class NativeImageBuildAction implements WorkAction { + + private final ExecOperations execOperations; + + @Inject + public NativeImageBuildAction(ExecOperations execOperations) { + this.execOperations = execOperations; + } + + @Override + public void execute() { + Parameters params = getParameters(); + String imageTag = params.getImageTag().get(); + String platform = params.getPlatform().get(); + String mainClass = params.getMainClass().get(); + File outputFile = params.getOutputFile().get().getAsFile(); + File outputDir = outputFile.getParentFile(); + + if (outputDir.exists() == false && outputDir.mkdirs() == false) { + throw new GradleException("Failed to create output directory: " + outputDir); + } + + List classpathFiles = params.getClasspath().getFiles().stream().filter(File::exists).collect(Collectors.toList()); + if (classpathFiles.isEmpty()) { + throw new GradleException("Native-image classpath is empty"); + } + + // Build classpath string for inside the container: /cp/0:/cp/1:... + List cpPaths = new ArrayList<>(); + for (int i = 0; i < classpathFiles.size(); i++) { + cpPaths.add("/cp/" + i); + } + // Container is always Linux + String cpString = String.join(":", cpPaths); + + List args = new ArrayList<>(); + args.add("run"); + args.add("--rm"); + for (int i = 0; i < classpathFiles.size(); i++) { + File f = classpathFiles.get(i); + String path = f.getAbsolutePath(); + if (File.separatorChar == '\\') { + path = path.replace("\\", "/"); + } + args.add("-v"); + args.add(path + ":/cp/" + i + ":ro"); + } + args.add("-v"); + String outPath = outputDir.getAbsolutePath(); + if (File.separatorChar == '\\') { + outPath = outPath.replace("\\", "/"); + } + args.add(outPath + ":/output"); + args.add("--platform"); + args.add(platform); + args.add(imageTag); + args.add("--no-fallback"); + if (params.getStatic().get()) { + args.add("--static"); + } + args.add("-cp"); + args.add(cpString); + args.add("-o"); + args.add("/output/" + outputFile.getName()); + args.add(mainClass); + + LoggedExec.exec(execOperations, spec -> { + maybeConfigureDockerConfig(spec); + spec.executable(params.getDockerExecutable().get()); + spec.args(args); + }); + } + + private void maybeConfigureDockerConfig(ExecSpec spec) { + String dockerConfig = System.getenv("DOCKER_CONFIG"); + if (dockerConfig != null) { + spec.environment("DOCKER_CONFIG", dockerConfig); + } + } + } +} diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/Architecture.java b/build-tools/src/main/java/org/elasticsearch/gradle/Architecture.java index c2654f9ae851f..b17365b4f7a73 100644 --- a/build-tools/src/main/java/org/elasticsearch/gradle/Architecture.java +++ b/build-tools/src/main/java/org/elasticsearch/gradle/Architecture.java @@ -9,6 +9,8 @@ package org.elasticsearch.gradle; +import java.util.Optional; + public enum Architecture { X64("x86_64", "linux/amd64", "amd64", "x64"), @@ -35,4 +37,23 @@ public static Architecture current() { }; } + /** + * Returns the architecture that matches the given Docker platform string (e.g. "linux/amd64"). + * + * @param platform the Docker platform string from e.g. {@code docker buildx inspect} + * @return the matching architecture, or empty if unknown + */ + public static Optional fromDockerPlatform(String platform) { + if (platform == null || platform.isBlank()) { + return Optional.empty(); + } + String trimmed = platform.trim(); + for (Architecture a : values()) { + if (a.dockerPlatform.equals(trimmed)) { + return Optional.of(a); + } + } + return Optional.empty(); + } + } diff --git a/distribution/build.gradle b/distribution/build.gradle index b419fb6be6738..bb2b75b7a8826 100644 --- a/distribution/build.gradle +++ b/distribution/build.gradle @@ -295,7 +295,7 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) { * Properties to expand when copying packaging files * *****************************************************************************/ configurations { - ['libs', 'libsVersionChecker', 'libsCliLauncher', 'libsServerCli', 'libsWindowsServiceCli', 'libsPluginCli', 'libsKeystoreCli', 'libsSecurityCli', 'libsGeoIpCli', 'libsAnsiConsole', 'libsNative', 'libsEntitlementAgent'].each { + ['libs', 'libsVersionChecker', 'libsCliLauncher', 'libsServerCli', 'libsServerLauncher', 'libsServerLauncherNativeX64', 'libsServerLauncherNativeAarch64', 'libsWindowsServiceCli', 'libsPluginCli', 'libsKeystoreCli', 'libsSecurityCli', 'libsGeoIpCli', 'libsAnsiConsole', 'libsNative', 'libsEntitlementAgent'].each { create(it) { canBeConsumed = false canBeResolved = true @@ -335,6 +335,9 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) { libsVersionChecker project(':distribution:tools:java-version-checker') libsCliLauncher project(':distribution:tools:cli-launcher') libsServerCli project(':distribution:tools:server-cli') + libsServerLauncher project(':distribution:tools:server-launcher') + libsServerLauncherNativeX64 project(path: ':distribution:tools:server-launcher', configuration: 'nativeLinuxX64') + libsServerLauncherNativeAarch64 project(path: ':distribution:tools:server-launcher', configuration: 'nativeLinuxAarch64') libsWindowsServiceCli project(':distribution:tools:windows-service-cli') libsAnsiConsole project(':distribution:tools:ansi-console') libsPluginCli project(':distribution:tools:plugin-cli') @@ -364,6 +367,22 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) { into('tools/server-cli') { from(configurations.libsServerCli) } + into('tools/server-launcher') { + from(configurations.libsServerLauncher) + // Linux-only: include native binary for the matching architecture + if (os == 'linux') { + if (architecture == 'x64') { + from(configurations.libsServerLauncherNativeX64) + } else if (architecture == 'aarch64') { + from(configurations.libsServerLauncherNativeAarch64) + } + } + eachFile { + if (it.name == 'server-launcher' || it.name == 'server-launcher.exe') { + it.permissions.unix(0755) + } + } + } into('tools/windows-service-cli') { from(configurations.libsWindowsServiceCli) } diff --git a/distribution/docker/build.gradle b/distribution/docker/build.gradle index 4d2a8dad29088..4f3c42b0cbef8 100644 --- a/distribution/docker/build.gradle +++ b/distribution/docker/build.gradle @@ -503,13 +503,6 @@ void addBuildDockerImageTask(Architecture architecture, DockerBase base) { } else { baseImages = [] } - - Provider serviceProvider = GradleUtils.getBuildService( - project.gradle.sharedServices, - DockerSupportPlugin.DOCKER_SUPPORT_SERVICE_NAME - ) - onlyIf("$architecture supported") { serviceProvider.get().isArchitectureSupported(architecture) } - } if (base != DockerBase.IRON_BANK && base != DockerBase.CLOUD_ESS) { @@ -576,11 +569,6 @@ void addBuildCloudDockerImageTasks(Architecture architecture) { baseImages = [] tags = generateTags(dockerBase, architecture) platforms.add(architecture.dockerPlatform) - Provider serviceProvider = GradleUtils.getBuildService( - project.gradle.sharedServices, - DockerSupportPlugin.DOCKER_SUPPORT_SERVICE_NAME - ) - onlyIf("$architecture supported") { serviceProvider.get().isArchitectureSupported(architecture) } } diff --git a/distribution/src/bin/elasticsearch b/distribution/src/bin/elasticsearch index 4f48aa8453d73..52b53ca5b9ecb 100755 --- a/distribution/src/bin/elasticsearch +++ b/distribution/src/bin/elasticsearch @@ -1,5 +1,23 @@ #!/bin/bash -CLI_NAME=server -CLI_LIBS=lib/tools/server-cli -source "`dirname "$0"`"/elasticsearch-cli +source "`dirname "$0"`"/elasticsearch-env + +# use a small heap size for the CLI tools, and thus the serial collector to +# avoid stealing many CPU cycles; a user can override by setting CLI_JAVA_OPTS +CLI_JAVA_OPTS="-Xms4m -Xmx64m -XX:+UseSerialGC ${CLI_JAVA_OPTS}" + +export JAVA ES_HOME ES_PATH_CONF ES_DISTRIBUTION_TYPE JAVA_TYPE CLI_JAVA_OPTS + +NATIVE_LAUNCHER="$ES_HOME/lib/tools/server-launcher/server-launcher" +LAUNCHER_LIBS=$ES_HOME/lib/tools/server-launcher/* + +if [ -x "$NATIVE_LAUNCHER" ]; then + exec "$NATIVE_LAUNCHER" "$@" +else + exec \ + "$JAVA" \ + $CLI_JAVA_OPTS \ + -cp "$LAUNCHER_LIBS" \ + org.elasticsearch.server.launcher.ServerLauncher \ + "$@" +fi diff --git a/distribution/src/bin/elasticsearch.bat b/distribution/src/bin/elasticsearch.bat index c12d7088f6b3e..eb11582145ca0 100644 --- a/distribution/src/bin/elasticsearch.bat +++ b/distribution/src/bin/elasticsearch.bat @@ -3,13 +3,18 @@ setlocal enabledelayedexpansion setlocal enableextensions -set CLI_NAME=server -set CLI_LIBS=lib/tools/server-cli -call "%~dp0elasticsearch-cli.bat" ^ - %%* ^ - || goto exit +call "%~dp0elasticsearch-env.bat" || exit /b 1 + +rem use a small heap size for the CLI tools, and thus the serial collector to +rem avoid stealing many CPU cycles; a user can override by setting CLI_JAVA_OPTS +set CLI_JAVA_OPTS=-Xms4m -Xmx64m -XX:+UseSerialGC %CLI_JAVA_OPTS% + +%JAVA% ^ + %CLI_JAVA_OPTS% ^ + -cp "%ES_HOME%\lib\tools\server-launcher\*" ^ + org.elasticsearch.server.launcher.ServerLauncher ^ + %* endlocal endlocal -:exit exit /b %ERRORLEVEL% diff --git a/distribution/tools/cli-launcher/src/main/java/org/elasticsearch/launcher/CliToolLauncher.java b/distribution/tools/cli-launcher/src/main/java/org/elasticsearch/launcher/CliToolLauncher.java index 7ffc9276e2f40..9eb0b854d1567 100644 --- a/distribution/tools/cli-launcher/src/main/java/org/elasticsearch/launcher/CliToolLauncher.java +++ b/distribution/tools/cli-launcher/src/main/java/org/elasticsearch/launcher/CliToolLauncher.java @@ -21,6 +21,8 @@ import java.io.Closeable; import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; import java.util.Map; /** @@ -49,7 +51,14 @@ class CliToolLauncher { * @param args args to the tool * @throws Exception if the tool fails with an unknown error */ + @SuppressForbidden(reason = "uses System.out and System.err") public static void main(String[] args) throws Exception { + OutputStream originalStdOut = null; + if (isRedirectStdoutToStderr()) { + originalStdOut = System.out; + setOutToStderr(); + } + ProcessInfo pinfo = ProcessInfo.fromSystem(); // configure logging as early as possible @@ -59,7 +68,7 @@ public static void main(String[] args) throws Exception { String libs = pinfo.sysprops().getOrDefault("cli.libs", ""); command = CliToolProvider.load(pinfo.sysprops(), toolname, libs).create(); - Terminal terminal = Terminal.DEFAULT; + Terminal terminal = originalStdOut != null ? new RedirectedStdoutTerminal(originalStdOut) : Terminal.DEFAULT; Runtime.getRuntime().addShutdownHook(createShutdownHook(terminal, command)); int exitCode = command.main(args, terminal, pinfo); @@ -69,6 +78,21 @@ public static void main(String[] args) throws Exception { } } + /** + * Returns true when stdout should be redirected to stderr so that the real + * stdout can be used for binary output (e.g. the launch descriptor). + */ + @SuppressForbidden(reason = "Check redirect env and sysprop") + static boolean isRedirectStdoutToStderr() { + return "true".equalsIgnoreCase(System.getenv("ES_REDIRECT_STDOUT_TO_STDERR")) + || "true".equalsIgnoreCase(System.getProperty("cli.redirectStdoutToStderr", "")); + } + + @SuppressForbidden(reason = "Redirect stdout to stderr so binary output can use real stdout") + private static void setOutToStderr() { + System.setOut(new PrintStream(System.err)); + } + // package private for tests static String getToolName(Map sysprops) { String toolname = sysprops.getOrDefault("cli.name", ""); diff --git a/distribution/tools/cli-launcher/src/main/java/org/elasticsearch/launcher/RedirectedStdoutTerminal.java b/distribution/tools/cli-launcher/src/main/java/org/elasticsearch/launcher/RedirectedStdoutTerminal.java new file mode 100644 index 0000000000000..b1db85ae2c59a --- /dev/null +++ b/distribution/tools/cli-launcher/src/main/java/org/elasticsearch/launcher/RedirectedStdoutTerminal.java @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.launcher; + +import org.elasticsearch.cli.Terminal; +import org.elasticsearch.core.SuppressForbidden; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.nio.charset.Charset; + +/** + * A terminal that sends all print output to stderr and exposes the real stdout + * via {@link #getOutputStream()}. Used when the process is run with + * ES_REDIRECT_STDOUT_TO_STDERR (or cli.redirectStdoutToStderr) so that + * binary data (e.g. the launch descriptor) can be written to stdout while + * user-visible output goes to stderr. + */ +class RedirectedStdoutTerminal extends Terminal { + + private final OutputStream stdoutForBinary; + + @SuppressForbidden(reason = "Use stderr for all print output; stdout reserved for binary (e.g. descriptor)") + RedirectedStdoutTerminal(OutputStream stdoutForBinary) { + super( + new InputStreamReader(System.in, Charset.defaultCharset()), + new PrintWriter(System.err, true), + new PrintWriter(System.err, true) + ); + this.stdoutForBinary = stdoutForBinary; + } + + @Override + @SuppressForbidden(reason = "Expose stdin for binary input (e.g. keystore prompts)") + public InputStream getInputStream() { + return System.in; + } + + @Override + public OutputStream getOutputStream() { + return stdoutForBinary; + } +} diff --git a/distribution/tools/cli-launcher/src/test/java/org/elasticsearch/launcher/CliToolLauncherTests.java b/distribution/tools/cli-launcher/src/test/java/org/elasticsearch/launcher/CliToolLauncherTests.java index df11a529d7a19..569c5fa742005 100644 --- a/distribution/tools/cli-launcher/src/test/java/org/elasticsearch/launcher/CliToolLauncherTests.java +++ b/distribution/tools/cli-launcher/src/test/java/org/elasticsearch/launcher/CliToolLauncherTests.java @@ -10,10 +10,15 @@ package org.elasticsearch.launcher; import org.elasticsearch.cli.MockTerminal; +import org.elasticsearch.core.SuppressForbidden; import org.elasticsearch.test.ESTestCase; +import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.IOException; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; @@ -23,7 +28,9 @@ import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertArrayEquals; +@SuppressForbidden(reason = "uses System.out and System.err") public class CliToolLauncherTests extends ESTestCase { public void testCliNameSysprop() { @@ -61,4 +68,100 @@ public void testShutdownHookError() { // ensure that we dump the stack trace too assertThat(terminal.getErrorOutput(), containsString("at org.elasticsearch.launcher.CliToolLauncherTests.lambda")); } + + public void testConsoleOutputWithoutRedirectFlag() throws Exception { + Path esHome = createTempDir(); + ByteArrayOutputStream stdoutCapture = new ByteArrayOutputStream(); + ByteArrayOutputStream stderrCapture = new ByteArrayOutputStream(); + PrintStream savedOut = System.out; + PrintStream savedErr = System.err; + String savedEsPathHome = System.getProperty("es.path.home"); + String savedCliName = System.getProperty("cli.name"); + String savedCliLibs = System.getProperty("cli.libs"); + try { + System.setOut(new PrintStream(stdoutCapture, true, StandardCharsets.UTF_8)); + System.setErr(new PrintStream(stderrCapture, true, StandardCharsets.UTF_8)); + System.setProperty("es.path.home", esHome.toString()); + System.setProperty("cli.name", "redirect-test"); + System.setProperty("cli.libs", ""); + CliToolLauncher.main(new String[0]); + } finally { + System.setOut(savedOut); + System.setErr(savedErr); + restoreOrClear("es.path.home", savedEsPathHome); + restoreOrClear("cli.name", savedCliName); + restoreOrClear("cli.libs", savedCliLibs); + } + // Without redirect, getOutputStream() returns current System.out (our capture), so sentinel bytes appear on stdout + String stdout = stdoutCapture.toString(StandardCharsets.UTF_8); + assertThat(stdout, containsString(new String(RedirectTestCommand.SENTINEL_BYTES, StandardCharsets.UTF_8))); + } + + public void testWithRedirectFlagGetOutputStreamDirectsToStdout() throws Exception { + Path esHome = createTempDir(); + ByteArrayOutputStream stdoutCapture = new ByteArrayOutputStream(); + ByteArrayOutputStream stderrCapture = new ByteArrayOutputStream(); + PrintStream savedOut = System.out; + PrintStream savedErr = System.err; + String savedEsPathHome = System.getProperty("es.path.home"); + String savedCliName = System.getProperty("cli.name"); + String savedCliLibs = System.getProperty("cli.libs"); + String savedRedirect = System.getProperty("cli.redirectStdoutToStderr"); + try { + System.setOut(new PrintStream(stdoutCapture, true, StandardCharsets.UTF_8)); + System.setErr(new PrintStream(stderrCapture, true, StandardCharsets.UTF_8)); + System.setProperty("es.path.home", esHome.toString()); + System.setProperty("cli.name", "redirect-test"); + System.setProperty("cli.libs", ""); + System.setProperty("cli.redirectStdoutToStderr", "true"); + CliToolLauncher.main(new String[0]); + } finally { + System.setOut(savedOut); + System.setErr(savedErr); + restoreOrClear("es.path.home", savedEsPathHome); + restoreOrClear("cli.name", savedCliName); + restoreOrClear("cli.libs", savedCliLibs); + restoreOrClear("cli.redirectStdoutToStderr", savedRedirect); + } + byte[] stdoutBytes = stdoutCapture.toByteArray(); + assertArrayEquals(RedirectTestCommand.SENTINEL_BYTES, stdoutBytes); + } + + public void testWithRedirectFlagUserOutputGoesToStderr() throws Exception { + Path esHome = createTempDir(); + ByteArrayOutputStream stdoutCapture = new ByteArrayOutputStream(); + ByteArrayOutputStream stderrCapture = new ByteArrayOutputStream(); + PrintStream savedOut = System.out; + PrintStream savedErr = System.err; + String savedEsPathHome = System.getProperty("es.path.home"); + String savedCliName = System.getProperty("cli.name"); + String savedCliLibs = System.getProperty("cli.libs"); + String savedRedirect = System.getProperty("cli.redirectStdoutToStderr"); + try { + System.setOut(new PrintStream(stdoutCapture, true, StandardCharsets.UTF_8)); + System.setErr(new PrintStream(stderrCapture, true, StandardCharsets.UTF_8)); + System.setProperty("es.path.home", esHome.toString()); + System.setProperty("cli.name", "redirect-test"); + System.setProperty("cli.libs", ""); + System.setProperty("cli.redirectStdoutToStderr", "true"); + CliToolLauncher.main(new String[0]); + } finally { + System.setOut(savedOut); + System.setErr(savedErr); + restoreOrClear("es.path.home", savedEsPathHome); + restoreOrClear("cli.name", savedCliName); + restoreOrClear("cli.libs", savedCliLibs); + restoreOrClear("cli.redirectStdoutToStderr", savedRedirect); + } + String stderr = stderrCapture.toString(StandardCharsets.UTF_8); + assertThat(stderr, containsString(RedirectTestCommand.USER_OUTPUT)); + } + + private static void restoreOrClear(String key, String value) { + if (value != null) { + System.setProperty(key, value); + } else { + System.clearProperty(key); + } + } } diff --git a/distribution/tools/cli-launcher/src/test/java/org/elasticsearch/launcher/RedirectTestCliToolProvider.java b/distribution/tools/cli-launcher/src/test/java/org/elasticsearch/launcher/RedirectTestCliToolProvider.java new file mode 100644 index 0000000000000..dffb8ec5891c5 --- /dev/null +++ b/distribution/tools/cli-launcher/src/test/java/org/elasticsearch/launcher/RedirectTestCliToolProvider.java @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.launcher; + +import org.elasticsearch.cli.CliToolProvider; +import org.elasticsearch.cli.Command; + +/** + * Test CliToolProvider that supplies {@link RedirectTestCommand} for redirect tests. + */ +public class RedirectTestCliToolProvider implements CliToolProvider { + + @Override + public String name() { + return "redirect-test"; + } + + @Override + public Command create() { + return new RedirectTestCommand(); + } +} diff --git a/distribution/tools/cli-launcher/src/test/java/org/elasticsearch/launcher/RedirectTestCommand.java b/distribution/tools/cli-launcher/src/test/java/org/elasticsearch/launcher/RedirectTestCommand.java new file mode 100644 index 0000000000000..630775aa0f3f0 --- /dev/null +++ b/distribution/tools/cli-launcher/src/test/java/org/elasticsearch/launcher/RedirectTestCommand.java @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.launcher; + +import joptsimple.OptionSet; + +import org.elasticsearch.cli.Command; +import org.elasticsearch.cli.ProcessInfo; +import org.elasticsearch.cli.Terminal; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +/** + * A test command that prints user output and optionally writes sentinel bytes + * to the terminal's output stream. Used to verify redirect behavior. + */ +public class RedirectTestCommand extends Command { + + static final String USER_OUTPUT = "user-output"; + static final byte[] SENTINEL_BYTES = "DESC".getBytes(StandardCharsets.UTF_8); + + RedirectTestCommand() { + super("redirect test command"); + } + + @Override + protected void execute(Terminal terminal, OptionSet options, ProcessInfo processInfo) throws Exception { + terminal.println(USER_OUTPUT); + var out = terminal.getOutputStream(); + if (out != null) { + out.write(SENTINEL_BYTES); + out.flush(); + } + } + + @Override + public void close() throws IOException {} +} diff --git a/distribution/tools/cli-launcher/src/test/resources/META-INF/services/org.elasticsearch.cli.CliToolProvider b/distribution/tools/cli-launcher/src/test/resources/META-INF/services/org.elasticsearch.cli.CliToolProvider new file mode 100644 index 0000000000000..30ccdeac0ac3f --- /dev/null +++ b/distribution/tools/cli-launcher/src/test/resources/META-INF/services/org.elasticsearch.cli.CliToolProvider @@ -0,0 +1 @@ +org.elasticsearch.launcher.RedirectTestCliToolProvider diff --git a/distribution/tools/server-cli/build.gradle b/distribution/tools/server-cli/build.gradle index 299d511ba5dbe..f9e2721f00e74 100644 --- a/distribution/tools/server-cli/build.gradle +++ b/distribution/tools/server-cli/build.gradle @@ -13,6 +13,7 @@ apply plugin: 'elasticsearch.build' dependencies { compileOnly project(":server") compileOnly project(":libs:cli") + implementation project(":libs:server-launcher-common") testImplementation project(":test:framework") } diff --git a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmArgumentParsingSystemMemoryInfo.java b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmArgumentParsingSystemMemoryInfo.java deleted file mode 100644 index b361d1d4bf275..0000000000000 --- a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmArgumentParsingSystemMemoryInfo.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -package org.elasticsearch.server.cli; - -import java.util.List; - -public abstract class JvmArgumentParsingSystemMemoryInfo implements SystemMemoryInfo { - private final List userDefinedJvmOptions; - - public JvmArgumentParsingSystemMemoryInfo(List userDefinedJvmOptions) { - this.userDefinedJvmOptions = userDefinedJvmOptions; - } - - protected long getBytesFromSystemProperty(String systemProperty, long defaultValue) { - return userDefinedJvmOptions.stream() - .filter(option -> option.startsWith("-D" + systemProperty + "=")) - .map(totalMemoryOverheadBytesOption -> { - try { - long bytes = Long.parseLong(totalMemoryOverheadBytesOption.split("=", 2)[1]); - if (bytes < 0) { - throw new IllegalArgumentException("Negative bytes size specified in [" + totalMemoryOverheadBytesOption + "]"); - } - return bytes; - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Unable to parse number of bytes from [" + totalMemoryOverheadBytesOption + "]", e); - } - }) - .reduce((previous, current) -> current) // this is effectively findLast(), so that ES_JAVA_OPTS overrides jvm.options - .orElse(defaultValue); - } -} diff --git a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmOptionsParser.java b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmOptionsParser.java index 3927bde0a054d..e97dc4c06f651 100644 --- a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmOptionsParser.java +++ b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmOptionsParser.java @@ -142,10 +142,7 @@ private List jvmOptions( } final List substitutedJvmOptions = substitutePlaceholders(jvmOptions, Collections.unmodifiableMap(substitutions)); - final SystemMemoryInfo memoryInfo = new OverheadSystemMemoryInfo( - substitutedJvmOptions, - new OverridableSystemMemoryInfo(substitutedJvmOptions, new DefaultSystemMemoryInfo()) - ); + final SystemMemoryInfo memoryInfo = new OverridableSystemMemoryInfo(substitutedJvmOptions, new DefaultSystemMemoryInfo()); substitutedJvmOptions.addAll(machineDependentHeap.determineHeapSettings(args.nodeSettings(), memoryInfo, substitutedJvmOptions)); final List ergonomicJvmOptions = JvmErgonomics.choose(substitutedJvmOptions, args.nodeSettings()); final List systemJvmOptions = SystemJvmOptions.systemJvmOptions(args.nodeSettings(), cliSysprops); diff --git a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/OverheadSystemMemoryInfo.java b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/OverheadSystemMemoryInfo.java deleted file mode 100644 index 5508c4f946680..0000000000000 --- a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/OverheadSystemMemoryInfo.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -package org.elasticsearch.server.cli; - -import java.util.List; - -/** - * A {@link SystemMemoryInfo} implementation that reduces the reported available system memory by a set amount. This is intended to account - * for overhead cost of other bundled Elasticsearch processes, such as the CLI tool launcher. By default, this is - * {@link org.elasticsearch.server.cli.OverheadSystemMemoryInfo#SERVER_CLI_OVERHEAD } but can be overridden via the - * {@code es.total_memory_overhead_bytes} system property. - */ -public class OverheadSystemMemoryInfo extends JvmArgumentParsingSystemMemoryInfo { - static final long SERVER_CLI_OVERHEAD = 100 * 1024L * 1024L; - - private final SystemMemoryInfo delegate; - - public OverheadSystemMemoryInfo(List userDefinedJvmOptions, SystemMemoryInfo delegate) { - super(userDefinedJvmOptions); - this.delegate = delegate; - } - - @Override - public long availableSystemMemory() { - long overheadBytes = getBytesFromSystemProperty("es.total_memory_overhead_bytes", SERVER_CLI_OVERHEAD); - return delegate.availableSystemMemory() - overheadBytes; - } -} diff --git a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/OverridableSystemMemoryInfo.java b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/OverridableSystemMemoryInfo.java index 2d9e32dd63be1..24dcac6013604 100644 --- a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/OverridableSystemMemoryInfo.java +++ b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/OverridableSystemMemoryInfo.java @@ -17,17 +17,33 @@ * has been specified using the {@code es.total_memory_bytes} system property, or * else returns the value provided by a fallback provider. */ -public final class OverridableSystemMemoryInfo extends JvmArgumentParsingSystemMemoryInfo { +public final class OverridableSystemMemoryInfo implements SystemMemoryInfo { + private final List userDefinedJvmOptions; private final SystemMemoryInfo fallbackSystemMemoryInfo; public OverridableSystemMemoryInfo(final List userDefinedJvmOptions, SystemMemoryInfo fallbackSystemMemoryInfo) { - super(userDefinedJvmOptions); + this.userDefinedJvmOptions = Objects.requireNonNull(userDefinedJvmOptions); this.fallbackSystemMemoryInfo = Objects.requireNonNull(fallbackSystemMemoryInfo); } @Override public long availableSystemMemory() { - return getBytesFromSystemProperty("es.total_memory_bytes", fallbackSystemMemoryInfo.availableSystemMemory()); + + return userDefinedJvmOptions.stream() + .filter(option -> option.startsWith("-Des.total_memory_bytes=")) + .map(totalMemoryBytesOption -> { + try { + long bytes = Long.parseLong(totalMemoryBytesOption.split("=", 2)[1]); + if (bytes < 0) { + throw new IllegalArgumentException("Negative memory size specified in [" + totalMemoryBytesOption + "]"); + } + return bytes; + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Unable to parse number of bytes from [" + totalMemoryBytesOption + "]", e); + } + }) + .reduce((previous, current) -> current) // this is effectively findLast(), so that ES_JAVA_OPTS overrides jvm.options + .orElse(fallbackSystemMemoryInfo.availableSystemMemory()); } } diff --git a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ServerCli.java b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ServerCli.java index 358358c81407a..fd8b2fc344cb0 100644 --- a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ServerCli.java +++ b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ServerCli.java @@ -22,22 +22,33 @@ import org.elasticsearch.cli.ProcessInfo; import org.elasticsearch.cli.Terminal; import org.elasticsearch.cli.UserException; +import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.cli.EnvironmentAwareCommand; +import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.settings.SecureSettings; import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.env.Environment; import org.elasticsearch.monitor.jvm.JvmInfo; +import org.elasticsearch.server.launcher.common.LaunchDescriptor; +import java.io.DataOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; +import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; /** - * The main CLI for running Elasticsearch. + * The main CLI for preparing the Elasticsearch server launch. + * + *

This program (the "preparer") does all the heavy lifting: parsing options, loading secure + * settings, auto-configuring security, syncing plugins, computing JVM options, and building the + * full command line. It then writes a {@link LaunchDescriptor} to stdout and exits. The + * server-launcher runs the preparer with stdout redirected and reads the descriptor from the + * preparer's stdout pipe, then spawns the actual server process. */ class ServerCli extends EnvironmentAwareCommand { @@ -47,10 +58,6 @@ class ServerCli extends EnvironmentAwareCommand { private final OptionSpecBuilder quietOption; private final OptionSpec enrollmentTokenOption; - // flag for indicating shutdown has begun. we use an AtomicBoolean to double as a synchronization object - private final AtomicBoolean shuttingDown = new AtomicBoolean(false); - private volatile ServerProcess server; - // visible for testing ServerCli() { super("Starts Elasticsearch"); // we configure logging later, so we override the base class from configuring logging @@ -103,35 +110,7 @@ public void execute(Terminal terminal, OptionSet options, Environment env, Proce syncPlugins(terminal, env, processInfo); ServerArgs args = createArgs(options, env, secrets, processInfo); - synchronized (shuttingDown) { - // if we are shutting down there is no reason to start the server - if (shuttingDown.get()) { - terminal.println("CLI is shutting down, skipping starting server process"); - return; - } - this.server = startServer(terminal, processInfo, args); - } - } - - if (options.has(daemonizeOption)) { - server.detach(); - return; - } - - // Call the GC to try and free up as much heap as we can since we don't intend to do much if any more allocation after this - System.gc(); - // we are running in the foreground, so wait for the server to exit - int exitCode = server.waitFor(); - onExit(exitCode); - } - - /** - * A post-exit hook to perform additional processing before the command terminates - * @param exitCode the server process exit code - */ - protected void onExit(int exitCode) throws UserException { - if (exitCode != ExitCodes.OK) { - throw new UserException(exitCode, "Elasticsearch exited unexpectedly"); + prepareLaunch(terminal, processInfo, args, options.has(daemonizeOption)); } } @@ -245,36 +224,80 @@ private ServerArgs createArgs(OptionSet options, Environment env, SecureSettings return new ServerArgs(daemonize, quiet, pidFile, secrets, env.settings(), env.configDir(), env.logsDir()); } - @Override - public void close() throws IOException { - synchronized (shuttingDown) { - shuttingDown.set(true); - if (server != null) { - server.stop(); - } - } - } - - // allow subclasses to access the started process - protected ServerProcess getServer() { - return server; - } - // protected to allow tests to override protected Command loadTool(Map sysprops, String toolname, String libs) { return CliToolProvider.load(sysprops, toolname, libs).create(); } + /** + * Builds a {@link LaunchDescriptor} with all the information the launcher needs to spawn + * the server process and writes it to the terminal's output stream (stdout when the + * launcher runs the preparer with redirect mode). + */ // protected to allow tests to override - protected ServerProcess startServer(Terminal terminal, ProcessInfo processInfo, ServerArgs args) throws Exception { + protected void prepareLaunch(Terminal terminal, ProcessInfo processInfo, ServerArgs args, boolean daemonize) throws Exception { var tempDir = ServerProcessUtils.setupTempDir(processInfo); var jvmOptions = JvmOptionsParser.determineJvmOptions(args, processInfo, tempDir, new MachineDependentHeap()); - var serverProcessBuilder = new ServerProcessBuilder().withTerminal(terminal) - .withProcessInfo(processInfo) - .withServerArgs(args) - .withTempDir(tempDir) - .withJvmOptions(jvmOptions); - return serverProcessBuilder.start(); + + String command = getJavaCommand(processInfo); + List jvmArgs = getJvmArgs(processInfo); + Map environment = getEnvironment(processInfo, tempDir); + byte[] serverArgsBytes = serializeServerArgs(args); + + LaunchDescriptor descriptor = new LaunchDescriptor( + command, + jvmOptions, + jvmArgs, + environment, + args.logsDir().toString(), + tempDir.toString(), + daemonize, + serverArgsBytes + ); + + var out = terminal.getOutputStream(); + if (out == null) { + throw new IllegalStateException("terminal.getOutputStream() is null; preparer must be run with ES_REDIRECT_STDOUT_TO_STDERR"); + } + DataOutputStream dos = new DataOutputStream(out); + descriptor.writeTo(dos); + dos.flush(); + } + + protected static String getJavaCommand(ProcessInfo processInfo) { + Path javaHome = Path.of(processInfo.sysprops().get("java.home")); + boolean isWindows = processInfo.sysprops().get("os.name").startsWith("Windows"); + return javaHome.resolve("bin").resolve("java" + (isWindows ? ".exe" : "")).toString(); + } + + protected static List getJvmArgs(ProcessInfo processInfo) { + Path esHome = processInfo.workingDir(); + return List.of( + "--module-path", + esHome.resolve("lib").toString(), + "--add-modules=jdk.net", + "--add-modules=jdk.management.agent", + "--add-modules=ALL-MODULE-PATH", + "-m", + "org.elasticsearch.server/org.elasticsearch.bootstrap.Elasticsearch" + ); + } + + protected static Map getEnvironment(ProcessInfo processInfo, Path tempDir) { + Map envVars = new HashMap<>(processInfo.envVars()); + envVars.remove("ES_TMPDIR"); + if (envVars.containsKey("LIBFFI_TMPDIR") == false) { + envVars.put("LIBFFI_TMPDIR", tempDir.toString()); + } + envVars.remove("ES_JAVA_OPTS"); + return envVars; + } + + protected static byte[] serializeServerArgs(ServerArgs args) throws IOException { + try (BytesStreamOutput out = new BytesStreamOutput()) { + args.writeTo(out); + return BytesReference.toBytes(out.bytes()); + } } // protected to allow tests to override diff --git a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ServerProcessBuilder.java b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ServerProcessBuilder.java deleted file mode 100644 index 375a12ea5cc7b..0000000000000 --- a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ServerProcessBuilder.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -package org.elasticsearch.server.cli; - -import org.elasticsearch.bootstrap.ServerArgs; -import org.elasticsearch.cli.ExitCodes; -import org.elasticsearch.cli.ProcessInfo; -import org.elasticsearch.cli.Terminal; -import org.elasticsearch.cli.UserException; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.io.stream.OutputStreamStreamOutput; -import org.elasticsearch.core.PathUtils; -import org.elasticsearch.core.SuppressForbidden; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.UncheckedIOException; -import java.nio.file.FileAlreadyExistsException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; - -/** - * This class is used to create a {@link ServerProcess}. - * Each ServerProcessBuilder instance manages a collection of process attributes. The {@link ServerProcessBuilder#start()} method creates - * a new {@link ServerProcess} instance with those attributes. - * - * Each process builder manages these process attributes: - * - a temporary directory - * - process info to pass through to the new Java subprocess - * - the command line arguments to run Elasticsearch - * - a list of JVM options to be passed to the Elasticsearch Java process - * - a {@link Terminal} to read input and write output from/to the cli console - */ -public class ServerProcessBuilder { - private Path tempDir; - private ServerArgs serverArgs; - private ProcessInfo processInfo; - private List jvmOptions; - private Terminal terminal; - - // this allows mocking the process building by tests - interface ProcessStarter { - Process start(ProcessBuilder pb) throws IOException; - } - - /** - * Specifies the temporary directory to be used by the server process - */ - public ServerProcessBuilder withTempDir(Path tempDir) { - this.tempDir = tempDir; - return this; - } - - /** - * Specifies the process info to pass through to the new Java subprocess - */ - public ServerProcessBuilder withProcessInfo(ProcessInfo processInfo) { - this.processInfo = processInfo; - return this; - } - - /** - * Specifies the command line arguments to run Elasticsearch - */ - public ServerProcessBuilder withServerArgs(ServerArgs serverArgs) { - this.serverArgs = serverArgs; - return this; - } - - /** - * Specifies the JVM options to be passed to the Elasticsearch Java process - */ - public ServerProcessBuilder withJvmOptions(List jvmOptions) { - this.jvmOptions = jvmOptions; - return this; - } - - /** - * Specifies the {@link Terminal} to use for reading input and writing output from/to the cli console - */ - public ServerProcessBuilder withTerminal(Terminal terminal) { - this.terminal = terminal; - return this; - } - - private Map getEnvironment() { - Map envVars = new HashMap<>(processInfo.envVars()); - - envVars.remove("ES_TMPDIR"); - if (envVars.containsKey("LIBFFI_TMPDIR") == false) { - envVars.put("LIBFFI_TMPDIR", tempDir.toString()); - } - envVars.remove("ES_JAVA_OPTS"); - - return envVars; - } - - private List getJvmArgs() { - Path esHome = processInfo.workingDir(); - return List.of( - "--module-path", - esHome.resolve("lib").toString(), - // Special circumstances require some modules (not depended on by the main server module) to be explicitly added: - "--add-modules=jdk.net", // needed to reflectively set extended socket options - "--add-modules=jdk.management.agent", // needed by external debug tools to grab thread and heap dumps - // we control the module path, which may have additional modules not required by server - "--add-modules=ALL-MODULE-PATH", - "-m", - "org.elasticsearch.server/org.elasticsearch.bootstrap.Elasticsearch" - ); - } - - private String getCommand() { - Path javaHome = PathUtils.get(processInfo.sysprops().get("java.home")); - - boolean isWindows = processInfo.sysprops().get("os.name").startsWith("Windows"); - return javaHome.resolve("bin").resolve("java" + (isWindows ? ".exe" : "")).toString(); - } - - /** - * Start a server in a new process. - * - * @return A running server process that is ready for requests - * @throws UserException If the process failed during bootstrap - */ - public ServerProcess start() throws UserException { - return start(ProcessBuilder::start); - } - - private void ensureWorkingDirExists() throws UserException { - Path workingDir = serverArgs.logsDir(); - try { - Files.createDirectories(workingDir); - } catch (FileAlreadyExistsException e) { - throw new UserException(ExitCodes.CONFIG, "Logs dir [" + workingDir + "] exists but is not a directory", e); - } catch (IOException e) { - throw new UserException(ExitCodes.CONFIG, "Unable to create logs dir [" + workingDir + "]", e); - } - } - - private static void checkRequiredArgument(Object argument, String argumentName) { - if (argument == null) { - throw new IllegalStateException( - Strings.format("'%s' is a required argument and needs to be specified before calling start()", argumentName) - ); - } - } - - // package private for testing - ServerProcess start(ProcessStarter processStarter) throws UserException { - checkRequiredArgument(tempDir, "tempDir"); - checkRequiredArgument(serverArgs, "serverArgs"); - checkRequiredArgument(processInfo, "processInfo"); - checkRequiredArgument(jvmOptions, "jvmOptions"); - checkRequiredArgument(terminal, "terminal"); - - ensureWorkingDirExists(); - - Process jvmProcess = null; - ErrorPumpThread errorPump; - - boolean success = false; - try { - jvmProcess = createProcess(getCommand(), getJvmArgs(), jvmOptions, getEnvironment(), serverArgs.logsDir(), processStarter); - errorPump = new ErrorPumpThread(terminal, jvmProcess.getErrorStream()); - errorPump.start(); - sendArgs(serverArgs, jvmProcess.getOutputStream()); - - boolean serverOk = errorPump.waitUntilReady(); - if (serverOk == false) { - // something bad happened, wait for the process to exit then rethrow - int exitCode = jvmProcess.waitFor(); - throw new UserException(exitCode, "Elasticsearch died while starting up"); - } - success = true; - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (IOException e) { - throw new UncheckedIOException(e); - } finally { - if (success == false && jvmProcess != null && jvmProcess.isAlive()) { - jvmProcess.destroyForcibly(); - } - } - - return new ServerProcess(jvmProcess, errorPump); - } - - private static Process createProcess( - String command, - List jvmArgs, - List jvmOptions, - Map environment, - Path workingDir, - ProcessStarter processStarter - ) throws InterruptedException, IOException { - - var builder = new ProcessBuilder(Stream.concat(Stream.of(command), Stream.concat(jvmOptions.stream(), jvmArgs.stream())).toList()); - builder.environment().putAll(environment); - setWorkingDir(builder, workingDir); - builder.redirectOutput(ProcessBuilder.Redirect.INHERIT); - - return processStarter.start(builder); - } - - @SuppressForbidden(reason = "ProcessBuilder takes File") - private static void setWorkingDir(ProcessBuilder builder, Path path) { - builder.directory(path.toFile()); - } - - private static void sendArgs(ServerArgs args, OutputStream processStdin) { - // DO NOT close the underlying process stdin, since we need to be able to write to it to signal exit - var out = new OutputStreamStreamOutput(processStdin); - try { - args.writeTo(out); - out.flush(); - } catch (IOException ignore) { - // A failure to write here means the process has problems, and it will die anyway. We let this fall through - // so the pump thread can complete, writing out the actual error. All we get here is the failure to write to - // the process pipe, which isn't helpful to print. - } - } -} diff --git a/distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/OverheadSystemMemoryInfoTests.java b/distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/OverheadSystemMemoryInfoTests.java deleted file mode 100644 index 447adf5f6ead4..0000000000000 --- a/distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/OverheadSystemMemoryInfoTests.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -package org.elasticsearch.server.cli; - -import org.elasticsearch.test.ESTestCase; - -import java.util.List; - -import static org.elasticsearch.server.cli.OverheadSystemMemoryInfo.SERVER_CLI_OVERHEAD; -import static org.hamcrest.Matchers.is; - -public class OverheadSystemMemoryInfoTests extends ESTestCase { - - private static final long TRUE_SYSTEM_MEMORY = 1024 * 1024 * 1024L; - - public void testNoOptions() { - final SystemMemoryInfo memoryInfo = new OverheadSystemMemoryInfo(List.of(), delegateSystemMemoryInfo()); - assertThat(memoryInfo.availableSystemMemory(), is(TRUE_SYSTEM_MEMORY - SERVER_CLI_OVERHEAD)); - } - - public void testNoOverrides() { - final SystemMemoryInfo memoryInfo = new OverheadSystemMemoryInfo(List.of("-Da=b", "-Dx=y"), delegateSystemMemoryInfo()); - assertThat(memoryInfo.availableSystemMemory(), is(TRUE_SYSTEM_MEMORY - SERVER_CLI_OVERHEAD)); - } - - public void testValidSingleOverride() { - final SystemMemoryInfo memoryInfo = new OverheadSystemMemoryInfo( - List.of("-Des.total_memory_overhead_bytes=50000"), - delegateSystemMemoryInfo() - ); - assertThat(memoryInfo.availableSystemMemory(), is(TRUE_SYSTEM_MEMORY - 50000)); - } - - public void testValidOverrideInList() { - final SystemMemoryInfo memoryInfo = new OverheadSystemMemoryInfo( - List.of("-Da=b", "-Des.total_memory_overhead_bytes=50000", "-Dx=y"), - delegateSystemMemoryInfo() - ); - assertThat(memoryInfo.availableSystemMemory(), is(TRUE_SYSTEM_MEMORY - 50000)); - } - - public void testMultipleValidOverridesInList() { - final SystemMemoryInfo memoryInfo = new OverheadSystemMemoryInfo( - List.of("-Des.total_memory_overhead_bytes=50000", "-Da=b", "-Des.total_memory_overhead_bytes=100000", "-Dx=y"), - delegateSystemMemoryInfo() - ); - assertThat(memoryInfo.availableSystemMemory(), is(TRUE_SYSTEM_MEMORY - 100000)); - } - - public void testNegativeOverride() { - final SystemMemoryInfo memoryInfo = new OverheadSystemMemoryInfo( - List.of("-Da=b", "-Des.total_memory_overhead_bytes=-123", "-Dx=y"), - delegateSystemMemoryInfo() - ); - try { - memoryInfo.availableSystemMemory(); - fail("expected to fail"); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), is("Negative bytes size specified in [-Des.total_memory_overhead_bytes=-123]")); - } - } - - public void testUnparsableOverride() { - final SystemMemoryInfo memoryInfo = new OverheadSystemMemoryInfo( - List.of("-Da=b", "-Des.total_memory_overhead_bytes=invalid", "-Dx=y"), - delegateSystemMemoryInfo() - ); - try { - memoryInfo.availableSystemMemory(); - fail("expected to fail"); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), is("Unable to parse number of bytes from [-Des.total_memory_overhead_bytes=invalid]")); - } - } - - private static SystemMemoryInfo delegateSystemMemoryInfo() { - return () -> TRUE_SYSTEM_MEMORY; - } -} diff --git a/distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/OverridableSystemMemoryInfoTests.java b/distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/OverridableSystemMemoryInfoTests.java index b36947505f045..fb0a3fc630c7b 100644 --- a/distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/OverridableSystemMemoryInfoTests.java +++ b/distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/OverridableSystemMemoryInfoTests.java @@ -64,7 +64,7 @@ public void testNegativeOverride() { memoryInfo.availableSystemMemory(); fail("expected to fail"); } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), is("Negative bytes size specified in [-Des.total_memory_bytes=-123]")); + assertThat(e.getMessage(), is("Negative memory size specified in [-Des.total_memory_bytes=-123]")); } } diff --git a/distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/ServerCliTests.java b/distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/ServerCliTests.java index 2792dcd04986f..4a7b60d8979d9 100644 --- a/distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/ServerCliTests.java +++ b/distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/ServerCliTests.java @@ -34,12 +34,9 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Optional; -import java.util.concurrent.BrokenBarrierException; -import java.util.concurrent.CyclicBarrier; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; @@ -48,13 +45,9 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.emptyString; -import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.matchesRegex; import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.sameInstance; public class ServerCliTests extends CommandTestCase { @@ -150,17 +143,13 @@ public void testPidDirectories() throws Exception { assertOk("-p", "pid"); } - public void assertDaemonized(boolean daemonized, String... args) throws Exception { - argsValidator = serverArgs -> assertThat(serverArgs.daemonize(), equalTo(daemonized)); - assertOk(args); - assertThat(mockServer.detachCalled, is(daemonized)); - assertThat(mockServer.waitForCalled, not(equalTo(daemonized))); - } - public void testDaemonize() throws Exception { - assertDaemonized(true, "-d"); - assertDaemonized(true, "--daemonize"); - assertDaemonized(false); + argsValidator = serverArgs -> assertThat(serverArgs.daemonize(), equalTo(true)); + assertOk("-d"); + argsValidator = serverArgs -> assertThat(serverArgs.daemonize(), equalTo(true)); + assertOk("--daemonize"); + argsValidator = serverArgs -> assertThat(serverArgs.daemonize(), equalTo(false)); + assertOk(); } public void testQuiet() throws Exception { @@ -306,11 +295,12 @@ public void testKeystorePassword() throws Exception { assertKeystorePassword("a-dummy-password"); } - public void testCloseStopsServer() throws Exception { + public void testCloseIsNoop() throws Exception { + // The preparer no longer manages the server process, so close() is a no-op Command command = newCommand(); command.main(new String[0], terminal, new ProcessInfo(sysprops, envVars, esHomeDir)); command.close(); - assertThat(mockServer.stopCalled, is(true)); + // No assertions about server stopping - that's the launcher's job now } public void testIgnoreNullExceptionOutput() throws Exception { @@ -323,30 +313,11 @@ public void testIgnoreNullExceptionOutput() throws Exception { assertThat(terminal.getErrorOutput(), not(containsString("null"))); } - public void testOptionsBuildingInterrupted() throws IOException { - Command command = new TestServerCli() { - @Override - protected ServerProcess startServer(Terminal terminal, ProcessInfo processInfo, ServerArgs args) throws Exception { - throw new InterruptedException("interrupted while get jvm options"); - } - }; - - int exitCode = command.main(new String[0], terminal, new ProcessInfo(sysprops, envVars, esHomeDir)); - assertThat(exitCode, is(ExitCodes.CODE_ERROR)); - - String[] lines = terminal.getErrorOutput().split(System.lineSeparator()); - assertThat(List.of(lines), hasSize(greaterThan(10))); // at least decent sized stacktrace - assertThat(lines[0], is("java.lang.InterruptedException: interrupted while get jvm options")); - assertThat(lines[1], matchesRegex("\\tat org.elasticsearch.server.cli.ServerCliTests.+startServer\\(ServerCliTests.java:\\d+\\)")); - assertThat(lines[lines.length - 1], matchesRegex("\tat java.base/java.lang.Thread.run\\(Thread.java:\\d+\\)")); - - command.close(); - } - - public void testServerExitsNonZero() throws Exception { - mockServerExitCode = 140; - int exitCode = executeMain(); - assertThat(exitCode, equalTo(140)); + public void testPrepareLaunchCalled() throws Exception { + AtomicBoolean prepareLaunchCalled = new AtomicBoolean(false); + argsValidator = args -> prepareLaunchCalled.set(true); + assertOk(); + assertThat(prepareLaunchCalled.get(), is(true)); } public void testSecureSettingsLoaderChoice() throws Exception { @@ -388,52 +359,6 @@ public void testSecureSettingsLoaderWithNullPassword() throws Exception { assertEquals("", loader.password); } - public void testProcessCreationRace() throws Exception { - for (int i = 0; i < 10; ++i) { - CyclicBarrier raceStart = new CyclicBarrier(2); - TestServerCli cli = new TestServerCli() { - @Override - void syncPlugins(Terminal terminal, Environment env, ProcessInfo processInfo) throws Exception { - super.syncPlugins(terminal, env, processInfo); - raceStart.await(); - } - - @Override - public void close() throws IOException { - try { - raceStart.await(); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - throw new AssertionError(ie); - } catch (BrokenBarrierException e) { - throw new AssertionError(e); - } - super.close(); - } - }; - Thread closeThread = new Thread(() -> { - try { - cli.close(); - } catch (IOException e) { - throw new AssertionError(e); - } - }); - closeThread.start(); - cli.main(new String[] {}, terminal, new ProcessInfo(sysprops, envVars, esHomeDir)); - closeThread.join(); - - if (cli.getServer() == null) { - // close won the race, so server should never have been started - assertThat(cli.startServerCalled, is(false)); - } else { - // creation won the race, so check we correctly waited on it and stopped - assertThat(cli.getServer(), sameInstance(mockServer)); - assertThat(mockServer.waitForCalled, is(true)); - assertThat(mockServer.stopCalled, is(true)); - } - } - } - private MockSecureSettingsLoader loadWithMockSecureSettingsLoader() throws Exception { var loader = new MockSecureSettingsLoader(); this.mockSecureSettingsLoader = loader; @@ -454,8 +379,6 @@ interface AutoConfigMethod { } Consumer argsValidator; - private final MockServerProcess mockServer = new MockServerProcess(); - int mockServerExitCode = 0; AutoConfigMethod autoConfigCallback; private final MockAutoConfigCli AUTO_CONFIG_CLI = new MockAutoConfigCli(); @@ -472,7 +395,6 @@ public void resetCommand() { argsValidator = null; autoConfigCallback = null; syncPluginsCallback = null; - mockServerExitCode = 0; } private class MockAutoConfigCli extends EnvironmentAwareCommand { @@ -490,7 +412,6 @@ protected void execute(Terminal terminal, OptionSet options, ProcessInfo process @Override public void execute(Terminal terminal, OptionSet options, Environment env, ProcessInfo processInfo) throws Exception { - // TODO: fake errors, check password from terminal, allow tests to make elasticsearch.yml change if (autoConfigCallback != null) { autoConfigCallback.autoconfig(terminal, options, env, processInfo); } @@ -515,48 +436,7 @@ public void execute(Terminal terminal, OptionSet options, Environment env, Proce } } - private class MockServerProcess extends ServerProcess { - volatile boolean detachCalled = false; - volatile boolean waitForCalled = false; - volatile boolean stopCalled = false; - - MockServerProcess() { - super(null, null); - } - - @Override - public long pid() { - return 12345; - } - - @Override - public void detach() { - assert detachCalled == false; - detachCalled = true; - } - - @Override - public int waitFor() { - assert waitForCalled == false; - waitForCalled = true; - return mockServerExitCode; - } - - @Override - public void stop() { - assert stopCalled == false; - stopCalled = true; - } - - void reset() { - detachCalled = false; - waitForCalled = false; - stopCalled = false; - } - } - private class TestServerCli extends ServerCli { - boolean startServerCalled = false; @Override protected Command loadTool(Map sysprops, String toolname, String libs) { @@ -588,7 +468,6 @@ Environment autoConfigureSecurity( void syncPlugins(Terminal terminal, Environment env, ProcessInfo processInfo) throws Exception { if (mockSecureSettingsLoader != null && mockSecureSettingsLoader instanceof MockSecureSettingsLoader mock) { mock.verifiedEnv = true; - // equals as a pointer, environment shouldn't be changed if autoconfigure is not supported assertFalse(mockSecureSettingsLoader.supportsSecurityAutoConfiguration()); assertTrue(mock.environment == env); } @@ -606,13 +485,10 @@ protected SecureSettingsLoader secureSettingsLoader(Environment env) { } @Override - protected ServerProcess startServer(Terminal terminal, ProcessInfo processInfo, ServerArgs args) throws Exception { - startServerCalled = true; + protected void prepareLaunch(Terminal terminal, ProcessInfo processInfo, ServerArgs args, boolean daemonize) throws Exception { if (argsValidator != null) { argsValidator.accept(args); } - mockServer.reset(); - return mockServer; } } @@ -632,8 +508,6 @@ static class MockSecureSettingsLoader implements SecureSettingsLoader { @Override public SecureSettingsLoader.LoadedSecrets load(Environment environment, Terminal terminal) throws IOException { loaded = true; - // Stash the environment pointer, so we can compare it. Environment shouldn't be changed for - // loaders that don't autoconfigure. this.environment = environment; SecureString password = null; @@ -685,7 +559,6 @@ public LoadedSecrets load(Environment environment, Terminal terminal) throws Exc @Override public SecureSettings bootstrap(Environment environment, SecureString password) throws Exception { this.bootstrapped = true; - // make sure we don't fail in fips mode when we run with an empty password if (inFipsJvm() && (password == null || password.isEmpty())) { return KeyStoreWrapper.create(); } diff --git a/distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/ServerProcessTests.java b/distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/ServerProcessTests.java deleted file mode 100644 index 86bc336f0b4ba..0000000000000 --- a/distribution/tools/server-cli/src/test/java/org/elasticsearch/server/cli/ServerProcessTests.java +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -package org.elasticsearch.server.cli; - -import org.elasticsearch.bootstrap.BootstrapInfo; -import org.elasticsearch.bootstrap.ServerArgs; -import org.elasticsearch.cli.ExitCodes; -import org.elasticsearch.cli.MockTerminal; -import org.elasticsearch.cli.ProcessInfo; -import org.elasticsearch.cli.UserException; -import org.elasticsearch.common.io.stream.InputStreamStreamInput; -import org.elasticsearch.common.settings.KeyStoreWrapper; -import org.elasticsearch.common.settings.SecureSettings; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.core.IOUtils; -import org.elasticsearch.test.ESTestCase; -import org.junit.AfterClass; -import org.junit.Before; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; -import java.io.PrintStream; -import java.io.UncheckedIOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CancellationException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import static org.elasticsearch.bootstrap.BootstrapInfo.SERVER_READY_MARKER; -import static org.elasticsearch.server.cli.ProcessUtil.nonInterruptibleVoid; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasEntry; -import static org.hamcrest.Matchers.hasItems; -import static org.hamcrest.Matchers.hasKey; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; - -public class ServerProcessTests extends ESTestCase { - - private static final ExecutorService mockJvmProcessExecutor = Executors.newSingleThreadExecutor(); - final MockTerminal terminal = MockTerminal.create(); - protected final Map sysprops = new HashMap<>(); - protected final Map envVars = new HashMap<>(); - Path esHomeDir; - Path logsDir; - Settings.Builder nodeSettings; - ProcessValidator processValidator; - MainMethod mainCallback; - Runnable forceStopCallback; - MockElasticsearchProcess process; - SecureSettings secrets; - - interface MainMethod { - void main(ServerArgs args, InputStream stdin, PrintStream stderr, AtomicInteger exitCode) throws IOException; - } - - interface ProcessValidator { - void validate(ProcessBuilder processBuilder) throws IOException; - } - - int runForeground() throws Exception { - var server = startProcess(false, false); - return server.waitFor(); - } - - @Before - public void resetEnv() { - esHomeDir = createTempDir(); - terminal.reset(); - sysprops.clear(); - sysprops.put("os.name", "Linux"); - sysprops.put("java.home", "javahome"); - sysprops.put("es.path.home", esHomeDir.toString()); - logsDir = esHomeDir.resolve("logs"); - envVars.clear(); - nodeSettings = Settings.builder(); - processValidator = null; - mainCallback = null; - forceStopCallback = null; - secrets = KeyStoreWrapper.create(); - } - - @AfterClass - public static void cleanupExecutor() { - mockJvmProcessExecutor.shutdown(); - } - - // a "process" that is really another thread - private class MockElasticsearchProcess extends Process { - private final PipedOutputStream processStdin = new PipedOutputStream(); - private final PipedInputStream processStderr = new PipedInputStream(); - private final PipedInputStream stdin = new PipedInputStream(); - private final PipedOutputStream stderr = new PipedOutputStream(); - - private final AtomicInteger exitCode = new AtomicInteger(); - private final AtomicReference processException = new AtomicReference<>(); - private final AtomicReference assertion = new AtomicReference<>(); - private final Future main; - - MockElasticsearchProcess() throws IOException { - stdin.connect(processStdin); - stderr.connect(processStderr); - this.main = mockJvmProcessExecutor.submit(() -> { - var in = new InputStreamStreamInput(stdin); - try { - var serverArgs = new ServerArgs(in); - try (var err = new PrintStream(stderr, true, StandardCharsets.UTF_8)) { - if (mainCallback != null) { - mainCallback.main(serverArgs, stdin, err, exitCode); - } else { - err.println(SERVER_READY_MARKER); - } - } - } catch (IOException e) { - processException.set(e); - } catch (AssertionError e) { - assertion.set(e); - } - IOUtils.closeWhileHandlingException(stdin, stderr); - }); - } - - @Override - public OutputStream getOutputStream() { - return processStdin; - } - - @Override - public InputStream getInputStream() { - return InputStream.nullInputStream(); - } - - @Override - public InputStream getErrorStream() { - return processStderr; - } - - @Override - public long pid() { - return 12345; - } - - @Override - public int waitFor() throws InterruptedException { - try { - main.get(); - } catch (ExecutionException e) { - throw new AssertionError(e); - } catch (CancellationException e) { - return 137; // process killed - } - if (processException.get() != null) { - throw new AssertionError("Process failed", processException.get()); - } - if (assertion.get() != null) { - throw assertion.get(); - } - return exitCode.get(); - } - - @Override - public int exitValue() { - if (main.isDone() == false) { - throw new IllegalThreadStateException(); // match spec - } - return exitCode.get(); - } - - @Override - public void destroy() { - fail("Tried to kill ES process directly"); - } - - public Process destroyForcibly() { - main.cancel(true); - IOUtils.closeWhileHandlingException(stdin, stderr); - forceStopCallback.run(); - return this; - } - } - - ProcessInfo createProcessInfo() { - return new ProcessInfo(Map.copyOf(sysprops), Map.copyOf(envVars), esHomeDir); - } - - ServerArgs createServerArgs(boolean daemonize, boolean quiet) { - return new ServerArgs(daemonize, quiet, null, secrets, nodeSettings.build(), esHomeDir.resolve("config"), logsDir); - } - - ServerProcess startProcess(boolean daemonize, boolean quiet) throws Exception { - var pinfo = createProcessInfo(); - ServerProcessBuilder.ProcessStarter starter = pb -> { - if (processValidator != null) { - processValidator.validate(pb); - } - process = new MockElasticsearchProcess(); - return process; - }; - var serverProcessBuilder = new ServerProcessBuilder().withTerminal(terminal) - .withProcessInfo(pinfo) - .withServerArgs(createServerArgs(daemonize, quiet)) - .withJvmOptions(List.of()) - .withTempDir(ServerProcessUtils.setupTempDir(pinfo)); - return serverProcessBuilder.start(starter); - } - - public void testProcessBuilder() throws Exception { - processValidator = pb -> { - assertThat(pb.redirectInput(), equalTo(ProcessBuilder.Redirect.PIPE)); - assertThat(pb.redirectOutput(), equalTo(ProcessBuilder.Redirect.INHERIT)); - assertThat(pb.redirectError(), equalTo(ProcessBuilder.Redirect.PIPE)); - assertThat(String.valueOf(pb.directory()), equalTo(esHomeDir.resolve("logs").toString())); - }; - mainCallback = (args, stdin, stderr, exitCode) -> { - try (PrintStream err = new PrintStream(stderr, true, StandardCharsets.UTF_8)) { - err.println("stderr message"); - err.println(SERVER_READY_MARKER); - } - }; - runForeground(); - assertThat(terminal.getErrorOutput(), containsString("stderr message")); - } - - public void testPid() throws Exception { - var server = startProcess(true, false); - assertThat(server.pid(), equalTo(12345L)); - server.stop(); - } - - public void testBootstrapError() throws Exception { - mainCallback = (args, stdin, stderr, exitCode) -> { - stderr.println("a bootstrap exception"); - exitCode.set(ExitCodes.CONFIG); - }; - var e = expectThrows(UserException.class, this::runForeground); - assertThat(e.exitCode, equalTo(ExitCodes.CONFIG)); - assertThat(terminal.getErrorOutput(), containsString("a bootstrap exception")); - } - - public void testStartError() { - processValidator = pb -> { throw new IOException("something went wrong"); }; - var e = expectThrows(UncheckedIOException.class, this::runForeground); - assertThat(e.getCause().getMessage(), equalTo("something went wrong")); - } - - public void testEnvPassthrough() throws Exception { - envVars.put("MY_ENV", "foo"); - processValidator = pb -> { assertThat(pb.environment(), hasEntry(equalTo("MY_ENV"), equalTo("foo"))); }; - runForeground(); - } - - public void testLibffiEnv() throws Exception { - processValidator = pb -> { - assertThat(pb.environment(), hasKey("LIBFFI_TMPDIR")); - Path libffi = Paths.get(pb.environment().get("LIBFFI_TMPDIR")); - assertThat(Files.exists(libffi), is(true)); - }; - runForeground(); - envVars.put("LIBFFI_TMPDIR", "mylibffi_tmp"); - processValidator = pb -> { assertThat(pb.environment(), hasEntry(equalTo("LIBFFI_TMPDIR"), equalTo("mylibffi_tmp"))); }; - runForeground(); - } - - public void testEnvCleared() throws Exception { - Path customTmpDir = createTempDir(); - envVars.put("ES_TMPDIR", customTmpDir.toString()); - envVars.put("ES_JAVA_OPTS", "-Dmyoption=foo"); - - processValidator = pb -> { - assertThat(pb.environment(), not(hasKey("ES_TMPDIR"))); - assertThat(pb.environment(), not(hasKey("ES_JAVA_OPTS"))); - }; - runForeground(); - } - - public void testCommandLineSysprops() throws Exception { - ServerProcessBuilder.ProcessStarter starter = pb -> { - assertThat(pb.command(), hasItems("-Dfoo1=bar", "-Dfoo2=baz")); - process = new MockElasticsearchProcess(); - return process; - }; - var serverProcessBuilder = new ServerProcessBuilder().withTerminal(terminal) - .withProcessInfo(createProcessInfo()) - .withServerArgs(createServerArgs(false, false)) - .withJvmOptions(List.of("-Dfoo1=bar", "-Dfoo2=baz")) - .withTempDir(Path.of(".")); - serverProcessBuilder.start(starter).waitFor(); - } - - public void testServerProcessBuilderMissingArgumentError() throws Exception { - ServerProcessBuilder.ProcessStarter starter = pb -> new MockElasticsearchProcess(); - var serverProcessBuilder = new ServerProcessBuilder().withTerminal(terminal) - .withProcessInfo(createProcessInfo()) - .withServerArgs(createServerArgs(false, false)) - .withTempDir(Path.of(".")); - var ex = expectThrows(IllegalStateException.class, () -> serverProcessBuilder.start(starter).waitFor()); - assertThat(ex.getMessage(), equalTo("'jvmOptions' is a required argument and needs to be specified before calling start()")); - } - - public void testCommandLine() throws Exception { - String mainClass = "org.elasticsearch.server/org.elasticsearch.bootstrap.Elasticsearch"; - String modulePath = esHomeDir.resolve("lib").toString(); - Path javaBin = Paths.get("javahome").resolve("bin"); - AtomicReference expectedJava = new AtomicReference<>(javaBin.resolve("java").toString()); - processValidator = pb -> { assertThat(pb.command(), hasItems(expectedJava.get(), "--module-path", modulePath, "-m", mainClass)); }; - runForeground(); - - sysprops.put("os.name", "Windows 10"); - sysprops.put("java.io.tmpdir", createTempDir().toString()); - expectedJava.set(javaBin.resolve("java.exe").toString()); - runForeground(); - } - - public void testDetach() throws Exception { - mainCallback = (args, stdin, stderr, exitCode) -> { - assertThat(args.daemonize(), equalTo(true)); - stderr.println(SERVER_READY_MARKER); - stderr.println("final message"); - stderr.close(); - // will block until stdin closed manually after test - assertThat(stdin.read(), equalTo(-1)); - }; - var server = startProcess(true, false); - server.detach(); - assertThat(terminal.getErrorOutput(), containsString("final message")); - server.stop(); // this should be a noop, and will fail the stdin read assert above if shutdown sent - process.processStdin.close(); // unblock the "process" thread so it can exit - } - - public void testStop() throws Exception { - CountDownLatch mainReady = new CountDownLatch(1); - mainCallback = (args, stdin, stderr, exitCode) -> { - stderr.println(SERVER_READY_MARKER); - nonInterruptibleVoid(mainReady::await); - stderr.println("final message"); - }; - var server = startProcess(false, false); - mainReady.countDown(); - server.stop(); - assertThat(process.main.isDone(), is(true)); // stop should have waited - assertThat(terminal.getErrorOutput(), containsString("final message")); - } - - public void testForceStop() throws Exception { - CountDownLatch blockMain = new CountDownLatch(1); - CountDownLatch inMain = new CountDownLatch(1); - mainCallback = (args, stdin, stderr, exitCode) -> { - stderr.println(SERVER_READY_MARKER); - inMain.countDown(); - nonInterruptibleVoid(blockMain::await); - }; - var server = startProcess(false, false); - nonInterruptibleVoid(inMain::await); - forceStopCallback = blockMain::countDown; - server.forceStop(); - - assertThat(process.main.isCancelled(), is(true)); // stop should have waited - } - - public void testWaitFor() throws Exception { - CountDownLatch mainReady = new CountDownLatch(1); - mainCallback = (args, stdin, stderr, exitCode) -> { - stderr.println(SERVER_READY_MARKER); - mainReady.countDown(); - assertThat(stdin.read(), equalTo((int) BootstrapInfo.SERVER_SHUTDOWN_MARKER)); - stderr.println("final message"); - }; - var server = startProcess(false, false); - - CompletableFuture stopping = new CompletableFuture<>(); - new Thread(() -> { - try { - // simulate stop run as shutdown hook in another thread, eg from Ctrl-C - nonInterruptibleVoid(mainReady::await); - server.stop(); - stopping.complete(null); - } catch (Throwable e) { - stopping.completeExceptionally(e); - } - }).start(); - int exitCode = server.waitFor(); - assertThat(process.main.isDone(), is(true)); - assertThat(exitCode, equalTo(0)); - assertThat(terminal.getErrorOutput(), containsString("final message")); - // rethrow any potential exception observed while stopping - stopping.get(); - } - - public void testProcessDies() throws Exception { - CountDownLatch mainExit = new CountDownLatch(1); - mainCallback = (args, stdin, stderr, exitCode) -> { - stderr.println(SERVER_READY_MARKER); - stderr.println("fatal message"); - stderr.close(); // mimic pipe break if cli process dies - nonInterruptibleVoid(mainExit::await); - exitCode.set(-9); - }; - var server = startProcess(false, false); - mainExit.countDown(); - int exitCode = server.waitFor(); - assertThat(exitCode, equalTo(-9)); - } - - public void testLogsDirIsFile() throws Exception { - Files.createFile(logsDir); - var e = expectThrows(UserException.class, this::runForeground); - assertThat(e.getMessage(), containsString("exists but is not a directory")); - } - - public void testLogsDirCreateParents() throws Exception { - Path testDir = createTempDir(); - logsDir = testDir.resolve("subdir/logs"); - processValidator = pb -> assertThat(String.valueOf(pb.directory()), equalTo(logsDir.toString())); - runForeground(); - } - - public void testLogsCreateFailure() throws Exception { - Path testDir = createTempDir(); - Path parentFile = testDir.resolve("exists"); - Files.createFile(parentFile); - logsDir = parentFile.resolve("logs"); - var e = expectThrows(UserException.class, this::runForeground); - assertThat(e.getMessage(), containsString("Unable to create logs dir")); - } -} diff --git a/distribution/tools/server-launcher/build.gradle b/distribution/tools/server-launcher/build.gradle new file mode 100644 index 0000000000000..ea07d3d5dac14 --- /dev/null +++ b/distribution/tools/server-launcher/build.gradle @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ +import org.elasticsearch.gradle.VersionProperties +import org.elasticsearch.gradle.internal.docker.NativeImageBuildTask +import org.elasticsearch.gradle.internal.precommit.CheckForbiddenApisTask + +apply plugin: 'elasticsearch.build' + +configurations { + nativeLinuxX64 { + canBeConsumed = true + canBeResolved = false + } + nativeLinuxAarch64 { + canBeConsumed = true + canBeResolved = false + } +} + +dependencies { + implementation project(':libs:server-launcher-common') + testImplementation project(':test:framework') +} + +tasks.withType(CheckForbiddenApisTask).configureEach { + // ServerLauncher uses various forbidden APIs such as System.exit() and printing directly to stdout and stderr. + enabled = false +} + +// --- GraalVM native-image build (Linux only, Docker-based) --- +def graalVmMajor = VersionProperties.getBundledJdkMajorVersion() +def nativeImageImage = "ghcr.io/graalvm/native-image-community:${graalVmMajor}-ol8" +def launcherMainClass = 'org.elasticsearch.server.launcher.ServerLauncher' + +def nativeImageLinuxX64 = tasks.register('nativeImageLinuxX64', NativeImageBuildTask) { + description = 'Builds Linux x86_64 native server-launcher binary via Docker' + group = 'build' + classpath = sourceSets.main.runtimeClasspath + imageTag = nativeImageImage + platform = 'linux/amd64' + mainClass = launcherMainClass + outputFile = layout.buildDirectory.file('native/linux-x86_64/server-launcher') +} + +def nativeImageLinuxAarch64 = tasks.register('nativeImageLinuxAarch64', NativeImageBuildTask) { + description = 'Builds Linux aarch64 native server-launcher binary via Docker' + group = 'build' + classpath = sourceSets.main.runtimeClasspath + imageTag = nativeImageImage + platform = 'linux/arm64' + mainClass = launcherMainClass + outputFile = layout.buildDirectory.file('native/linux-aarch64/server-launcher') +} + +artifacts { + nativeLinuxX64(nativeImageLinuxX64) + nativeLinuxAarch64(nativeImageLinuxAarch64) +} diff --git a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ErrorPumpThread.java b/distribution/tools/server-launcher/src/main/java/org/elasticsearch/server/launcher/ErrorPumpThread.java similarity index 57% rename from distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ErrorPumpThread.java rename to distribution/tools/server-launcher/src/main/java/org/elasticsearch/server/launcher/ErrorPumpThread.java index 1498fc8ae86dc..126c599f574b2 100644 --- a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ErrorPumpThread.java +++ b/distribution/tools/server-launcher/src/main/java/org/elasticsearch/server/launcher/ErrorPumpThread.java @@ -7,49 +7,49 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.server.cli; +package org.elasticsearch.server.launcher; -import org.elasticsearch.bootstrap.BootstrapInfo; -import org.elasticsearch.cli.Terminal; -import org.elasticsearch.cli.Terminal.Verbosity; -import org.elasticsearch.common.regex.Regex; +import org.elasticsearch.server.launcher.common.ProcessUtil; import java.io.BufferedReader; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.util.concurrent.CountDownLatch; import java.util.function.Predicate; - -import static org.elasticsearch.bootstrap.BootstrapInfo.SERVER_READY_MARKER; -import static org.elasticsearch.server.cli.ProcessUtil.nonInterruptibleVoid; +import java.util.regex.Pattern; /** - * A thread which reads stderr of the jvm process and writes it to this process' stderr. + * A thread which reads stderr of the server JVM process and writes it to this process' stderr. * *

The thread watches for a special state marker from the process. The ascii character - * {@link BootstrapInfo#SERVER_READY_MARKER} signals the server is ready and the cli may - * detach if daemonizing. All other messages are passed through to stderr. + * {@code \u0018} signals the server is ready and the launcher may detach if daemonizing. + * All other messages are passed through to stderr. */ -class ErrorPumpThread extends Thread implements Closeable { +public class ErrorPumpThread extends Thread implements Closeable { + /** Messages / lines predicate to filter from the output. */ + private static final Predicate filter = Pattern.compile( + "WARNING: Using incubator modules: jdk\\.incubator\\.vector" + // requires log4j2 upgrade, see https://github.com/elastic/elasticsearch/issues/132035 + + "|WARNING: Use of the three-letter time zone ID .* is deprecated and it will be removed in a future release" + ).asMatchPredicate(); + + static final char SERVER_READY_MARKER = '\u0018'; + private final BufferedReader reader; - private final Terminal terminal; + private final PrintStream errOutput; - // a latch which changes state when the server is ready or has had a bootstrap error private final CountDownLatch readyOrDead = new CountDownLatch(1); - - // a flag denoting whether the ready marker has been received by the server process private volatile boolean ready; - - // an unexpected io failure that occurred while pumping stderr private volatile IOException ioFailure; - ErrorPumpThread(Terminal terminal, InputStream errInput) { - super("server-cli[stderr_pump]"); + public ErrorPumpThread(InputStream errInput, PrintStream errOutput) { + super("server-launcher[stderr_pump]"); this.reader = new BufferedReader(new InputStreamReader(errInput, StandardCharsets.UTF_8)); - this.terminal = terminal; + this.errOutput = errOutput; } private void checkForIoFailure() throws IOException { @@ -69,11 +69,11 @@ public void close() throws IOException { /** * Waits until the server ready marker has been received. * - * {@code true} if successful, {@code false} if a startup error occurred + * @return {@code true} if successful, {@code false} if a startup error occurred * @throws IOException if there was a problem reading from stderr of the process */ - boolean waitUntilReady() throws IOException { - nonInterruptibleVoid(readyOrDead::await); + public boolean waitUntilReady() throws IOException { + ProcessUtil.nonInterruptibleVoid(readyOrDead::await); checkForIoFailure(); return ready; } @@ -81,17 +81,10 @@ boolean waitUntilReady() throws IOException { /** * Waits for the stderr pump thread to exit. */ - void drain() { - nonInterruptibleVoid(this::join); + public void drain() { + ProcessUtil.nonInterruptibleVoid(this::join); } - /** Messages / lines predicate to filter from the output. */ - private static Predicate filter = Regex.simpleMatcher( - "WARNING: Using incubator modules: jdk.incubator.vector", - // requires log4j2 upgrade, see https://github.com/elastic/elasticsearch/issues/132035 - "WARNING: Use of the three-letter time zone ID * is deprecated and it will be removed in a future release" - ); - @Override public void run() { try { @@ -101,13 +94,13 @@ public void run() { ready = true; readyOrDead.countDown(); } else if (filter.test(line) == false) { - terminal.errorPrintln(Verbosity.SILENT, line, false); + errOutput.println(line); } } } catch (IOException e) { ioFailure = e; } finally { - terminal.flush(); + errOutput.flush(); readyOrDead.countDown(); } } diff --git a/distribution/tools/server-launcher/src/main/java/org/elasticsearch/server/launcher/ServerLauncher.java b/distribution/tools/server-launcher/src/main/java/org/elasticsearch/server/launcher/ServerLauncher.java new file mode 100644 index 0000000000000..550c4c28bd8fc --- /dev/null +++ b/distribution/tools/server-launcher/src/main/java/org/elasticsearch/server/launcher/ServerLauncher.java @@ -0,0 +1,331 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.server.launcher; + +import org.elasticsearch.server.launcher.common.LaunchDescriptor; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; + +/** + * Minimal launcher for the Elasticsearch server process. + * + *

This program is exec'd directly by the startup script. It spawns the preparer (server-cli) + * as a child process, reads the resulting {@link LaunchDescriptor}, spawns the server JVM process, + * pipes the serialized ServerArgs bytes to the server's stdin, pumps stderr for the ready marker, + * and waits for the server to exit. + * + *

This program has zero Elasticsearch dependencies beyond the shared launcher-common library. + * + *

Subclasses (e.g. {@code ServerlessServerLauncher}) can override lifecycle hooks to customize + * behavior without duplicating shared logic. + * + * @param the descriptor type, must extend {@link LaunchDescriptor} + */ +public class ServerLauncher { + + private final AtomicBoolean shuttingDown = new AtomicBoolean(false); + private volatile ServerProcess server; + + public static void main(String[] args) throws Exception { + new ServerLauncher().run(args); + } + + protected void run(String[] args) throws Exception { + Process preparerProcess = startPreparer(args); + D descriptor = readDescriptorFromPreparer(preparerProcess); + if (descriptor == null) { + return; + } + + installShutdownHook(); + + Process[] rawProcessHolder = new Process[1]; + server = startServer(descriptor, pb -> { + try { + Process p = startProcess(pb); + rawProcessHolder[0] = p; + return p; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + + onServerStarted(descriptor, server, rawProcessHolder[0]); + + if (descriptor.daemonize()) { + server.detach(); + onDaemonize(descriptor); + return; + } + + int exitCode = server.waitFor(); + onServerExit(descriptor, exitCode); + if (exitCode != 0) { + System.exit(exitCode); + } + } + + // ---- Overridable lifecycle hooks ---- + + /** + * Returns the CLI name passed as {@code -Dcli.name} to the preparer process. + */ + protected String cliName() { + return "server"; + } + + /** + * Returns the CLI libs path passed as {@code -Dcli.libs} to the preparer process. + */ + protected String cliLibs() { + return "lib/tools/server-cli"; + } + + /** + * Returns the name for the JVM shutdown hook thread. + */ + protected String shutdownHookName() { + return "server-launcher-shutdown"; + } + + /** + * Returns extra system property names to forward from the launcher to the preparer process. + */ + protected List extraPreparerSystemProperties() { + return List.of(); + } + + /** + * Reads a launch descriptor from the preparer's stdout stream. + * Returns null if no bytes were written (e.g. --version or --help was used). + *

+ * Subclasses override this to read their specific descriptor type. + */ + @SuppressWarnings("unchecked") + protected D readDescriptorFromStream(InputStream in) throws IOException { + byte[] bytes = in.readAllBytes(); + if (bytes.length == 0) { + return null; + } + return (D) LaunchDescriptor.readFrom(new DataInputStream(new ByteArrayInputStream(bytes))); + } + + /** + * Starts a process from the given builder. Subclasses can override to capture the raw process. + */ + protected Process startProcess(ProcessBuilder pb) throws IOException { + return pb.start(); + } + + /** + * Called after the server process has started and the ready marker has been received. + */ + protected void onServerStarted(D descriptor, ServerProcess server, Process rawProcess) throws IOException {} + + /** + * Called before returning in daemon mode, after the server has been detached. + */ + protected void onDaemonize(D descriptor) {} + + /** + * Called after the server process exits (non-daemon mode). + */ + protected void onServerExit(D descriptor, int exitCode) {} + + // ---- Shared logic (private) ---- + + private Process startPreparer(String[] userArgs) throws IOException { + String java = requireEnv("JAVA"); + String esHome = requireEnv("ES_HOME"); + String esPathConf = requireEnv("ES_PATH_CONF"); + String esDistType = System.getenv("ES_DISTRIBUTION_TYPE"); + String javaType = System.getenv("JAVA_TYPE"); + String cliJavaOpts = System.getenv("CLI_JAVA_OPTS"); + + String classpath = esHome + + File.separator + + "lib" + + File.separator + + "*" + + File.pathSeparator + + esHome + + File.separator + + "lib" + + File.separator + + "cli-launcher" + + File.separator + + "*"; + + List command = new ArrayList<>(); + command.add(java); + + if (cliJavaOpts != null && cliJavaOpts.isBlank() == false) { + Collections.addAll(command, cliJavaOpts.trim().split("\\s+")); + } + + command.add("-Dcli.name=" + cliName()); + command.add("-Dcli.libs=" + cliLibs()); + command.add("-Des.path.home=" + esHome); + command.add("-Des.path.conf=" + esPathConf); + if (esDistType != null) { + command.add("-Des.distribution.type=" + esDistType); + } + if (javaType != null) { + command.add("-Des.java.type=" + javaType); + } + + for (String prop : extraPreparerSystemProperties()) { + String value = System.getProperty(prop); + if (value != null) { + command.add("-D" + prop + "=" + value); + } + } + + command.add("-cp"); + command.add(classpath); + command.add("org.elasticsearch.launcher.CliToolLauncher"); + + command.addAll(Arrays.asList(userArgs)); + + ProcessBuilder pb = new ProcessBuilder(command); + pb.redirectInput(ProcessBuilder.Redirect.INHERIT); + pb.redirectOutput(ProcessBuilder.Redirect.PIPE); + pb.redirectError(ProcessBuilder.Redirect.INHERIT); + pb.environment().put("ES_REDIRECT_STDOUT_TO_STDERR", "true"); + + return pb.start(); + } + + private D readDescriptorFromPreparer(Process preparerProcess) throws Exception { + D descriptor = null; + Exception readException = null; + try { + descriptor = readDescriptorFromStream(preparerProcess.getInputStream()); + } catch (Exception e) { + readException = e; + } + int preparerExit = preparerProcess.waitFor(); + if (preparerExit != 0) { + System.exit(preparerExit); + } + if (readException != null) { + if (readException instanceof IOException io) { + throw new UncheckedIOException(io); + } + throw new RuntimeException(readException); + } + return descriptor; + } + + private void installShutdownHook() { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + synchronized (shuttingDown) { + shuttingDown.set(true); + if (server != null) { + try { + server.stop(); + } catch (IOException e) { + System.err.println("Error stopping server: " + e.getMessage()); + } + } + } + }, shutdownHookName())); + } + + /** + * Starts the server process from the given descriptor and process starter function. + * Package-visible for testing. + */ + ServerProcess startServer(LaunchDescriptor descriptor, Function processStarter) throws Exception { + ensureWorkingDirExists(descriptor.workingDir()); + + List command = new ArrayList<>(); + command.add(descriptor.command()); + command.addAll(descriptor.jvmOptions()); + command.addAll(descriptor.jvmArgs()); + + ProcessBuilder pb = new ProcessBuilder(command); + pb.environment().clear(); + pb.environment().putAll(descriptor.environment()); + pb.directory(new File(descriptor.workingDir())); + pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); + + Process jvmProcess = null; + ErrorPumpThread errorPump; + boolean success = false; + + try { + jvmProcess = processStarter.apply(pb); + errorPump = new ErrorPumpThread(jvmProcess.getErrorStream(), System.err); + errorPump.start(); + sendServerArgs(descriptor.serverArgsBytes(), jvmProcess.getOutputStream()); + + boolean serverOk = errorPump.waitUntilReady(); + if (serverOk == false) { + int exitCode = jvmProcess.waitFor(); + System.err.println("Elasticsearch died while starting up, exit code: " + exitCode); + System.exit(exitCode != 0 ? exitCode : 1); + } + success = true; + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new UncheckedIOException(e); + } finally { + if (success == false && jvmProcess != null && jvmProcess.isAlive()) { + jvmProcess.destroyForcibly(); + } + } + + return new ServerProcess(jvmProcess, errorPump); + } + + private static void ensureWorkingDirExists(String workingDir) throws Exception { + Path path = Path.of(workingDir); + if (Files.exists(path) && Files.isDirectory(path) == false) { + System.err.println("Error: working directory exists but is not a directory: " + workingDir); + System.exit(1); + } + Files.createDirectories(path); + } + + private static void sendServerArgs(byte[] serverArgsBytes, OutputStream processStdin) { + try { + processStdin.write(serverArgsBytes); + processStdin.flush(); + } catch (IOException ignore) { + // A failure to write here means the process has problems, and it will die anyway. + // The error pump thread will report the actual error. + } + } + + private static String requireEnv(String name) { + String value = System.getenv(name); + if (value == null || value.isBlank()) { + System.err.println("Error: required environment variable " + name + " is not set"); + System.exit(1); + } + return value; + } +} diff --git a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ServerProcess.java b/distribution/tools/server-launcher/src/main/java/org/elasticsearch/server/launcher/ServerProcess.java similarity index 54% rename from distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ServerProcess.java rename to distribution/tools/server-launcher/src/main/java/org/elasticsearch/server/launcher/ServerProcess.java index 89377b5b3f8bb..ac3c7566ca856 100644 --- a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ServerProcess.java +++ b/distribution/tools/server-launcher/src/main/java/org/elasticsearch/server/launcher/ServerProcess.java @@ -7,25 +7,17 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.server.cli; +package org.elasticsearch.server.launcher; -import org.elasticsearch.bootstrap.BootstrapInfo; -import org.elasticsearch.core.IOUtils; +import org.elasticsearch.server.launcher.common.ProcessUtil; import java.io.IOException; import java.io.OutputStream; -import static org.elasticsearch.server.cli.ProcessUtil.nonInterruptible; - /** * A helper to control a {@link Process} running the main Elasticsearch server. * - *

The process can be started by calling {@link ServerProcessBuilder#start()}. - * The process is controlled by internally sending arguments and control signals on stdin, - * and receiving control signals on stderr. The start method does not return until the - * server is ready to process requests and has exited the bootstrap thread. - * - *

The caller starting a {@link ServerProcess} can then do one of several things: + *

The caller can: *

    *
  • Block on the server process exiting, by calling {@link #waitFor()}
  • *
  • Detach from the server process by calling {@link #detach()}
  • @@ -34,16 +26,13 @@ */ public class ServerProcess { - // the actual java process of the server - private final Process jvmProcess; + static final char SERVER_SHUTDOWN_MARKER = '\u001B'; - // the thread pumping stderr watching for state change messages + private final Process jvmProcess; private final ErrorPumpThread errorPump; - - // a flag marking whether the streams of the java subprocess have been closed private volatile boolean detached = false; - ServerProcess(Process jvmProcess, ErrorPumpThread errorPump) { + public ServerProcess(Process jvmProcess, ErrorPumpThread errorPump) { this.jvmProcess = jvmProcess; this.errorPump = errorPump; } @@ -57,13 +46,14 @@ public long pid() { /** * Detaches the server process from the current process, enabling the current process to exit. - * - * @throws IOException If an I/O error occurred while reading stderr or closing any of the standard streams */ public synchronized void detach() throws IOException { errorPump.drain(); try { - IOUtils.close(jvmProcess.getOutputStream(), jvmProcess.getInputStream(), jvmProcess.getErrorStream(), errorPump); + jvmProcess.getOutputStream().close(); + jvmProcess.getInputStream().close(); + jvmProcess.getErrorStream().close(); + errorPump.close(); } finally { detached = true; } @@ -74,44 +64,29 @@ public synchronized void detach() throws IOException { */ public int waitFor() throws IOException { errorPump.drain(); - int exitCode = nonInterruptible(jvmProcess::waitFor); + int exitCode = ProcessUtil.nonInterruptible(jvmProcess::waitFor); errorPump.close(); return exitCode; } /** - * Stop the subprocess. - * - *

    This sends a special code, {@link BootstrapInfo#SERVER_SHUTDOWN_MARKER} to the stdin - * of the process, then waits for the process to exit. - * - *

    Note that if {@link #detach()} has been called, this method is a no-op. + * Stop the subprocess by sending the shutdown marker to stdin, then wait for exit. */ public synchronized void stop() throws IOException { if (detached) { return; } - sendShutdownMarker(); - waitFor(); // ignore exit code, we are already shutting down - } - - /** - * Stop the subprocess, sending a SIGKILL. - */ - public void forceStop() throws IOException { - assert detached == false; - jvmProcess.destroyForcibly(); waitFor(); } private void sendShutdownMarker() { try { OutputStream os = jvmProcess.getOutputStream(); - os.write(BootstrapInfo.SERVER_SHUTDOWN_MARKER); + os.write(SERVER_SHUTDOWN_MARKER); os.flush(); } catch (IOException e) { - // process is already effectively dead, fall through to wait for it, or should we SIGKILL? + // process is already effectively dead, fall through to wait for it } } } diff --git a/distribution/tools/server-launcher/src/test/java/org/elasticsearch/server/launcher/ErrorPumpThreadTests.java b/distribution/tools/server-launcher/src/test/java/org/elasticsearch/server/launcher/ErrorPumpThreadTests.java new file mode 100644 index 0000000000000..27c81de929226 --- /dev/null +++ b/distribution/tools/server-launcher/src/test/java/org/elasticsearch/server/launcher/ErrorPumpThreadTests.java @@ -0,0 +1,132 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.server.launcher; + +import org.elasticsearch.test.ESTestCase; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; + +/** + * Tests for {@link ErrorPumpThread}. + */ +public class ErrorPumpThreadTests extends ESTestCase { + + private PipedOutputStream processStderr; + private ByteArrayOutputStream capturedOutput; + private ErrorPumpThread pump; + + private void startPump() throws IOException { + processStderr = new PipedOutputStream(); + PipedInputStream pumpInput = new PipedInputStream(processStderr); + capturedOutput = new ByteArrayOutputStream(); + pump = new ErrorPumpThread(pumpInput, new PrintStream(capturedOutput, true, StandardCharsets.UTF_8)); + pump.start(); + } + + private void writeLine(String line) throws IOException { + processStderr.write((line + "\n").getBytes(StandardCharsets.UTF_8)); + processStderr.flush(); + } + + private void closeAndDrain() throws IOException { + processStderr.close(); + pump.drain(); + pump.close(); + } + + private String output() { + return capturedOutput.toString(StandardCharsets.UTF_8); + } + + public void testReadyMarkerSignalsReady() throws Exception { + startPump(); + writeLine(String.valueOf(ErrorPumpThread.SERVER_READY_MARKER)); + assertThat(pump.waitUntilReady(), is(true)); + closeAndDrain(); + } + + public void testReadyMarkerNotPassedToOutput() throws Exception { + startPump(); + writeLine(String.valueOf(ErrorPumpThread.SERVER_READY_MARKER)); + pump.waitUntilReady(); + closeAndDrain(); + assertThat(output(), not(containsString(String.valueOf(ErrorPumpThread.SERVER_READY_MARKER)))); + } + + public void testStreamCloseWithoutMarkerSignalsNotReady() throws Exception { + startPump(); + writeLine("some startup error"); + closeAndDrain(); + assertThat(pump.waitUntilReady(), is(false)); + } + + public void testRegularMessagesPassThrough() throws Exception { + startPump(); + writeLine(String.valueOf(ErrorPumpThread.SERVER_READY_MARKER)); + pump.waitUntilReady(); + writeLine("hello world"); + writeLine("another message"); + closeAndDrain(); + assertThat(output(), containsString("hello world")); + assertThat(output(), containsString("another message")); + } + + public void testFiltersIncubatorModulesWarning() throws Exception { + startPump(); + writeLine(String.valueOf(ErrorPumpThread.SERVER_READY_MARKER)); + pump.waitUntilReady(); + writeLine("WARNING: Using incubator modules: jdk.incubator.vector"); + writeLine("legitimate message"); + closeAndDrain(); + assertThat(output(), not(containsString("incubator"))); + assertThat(output(), containsString("legitimate message")); + } + + public void testFiltersTimezoneDeprecationWarning() throws Exception { + startPump(); + writeLine(String.valueOf(ErrorPumpThread.SERVER_READY_MARKER)); + pump.waitUntilReady(); + writeLine("WARNING: Use of the three-letter time zone ID EST is deprecated and it will be removed in a future release"); + writeLine("WARNING: Use of the three-letter time zone ID PST is deprecated and it will be removed in a future release"); + writeLine("keep this line"); + closeAndDrain(); + assertThat(output(), not(containsString("time zone"))); + assertThat(output(), containsString("keep this line")); + } + + public void testDoesNotFilterPartialMatch() throws Exception { + startPump(); + writeLine(String.valueOf(ErrorPumpThread.SERVER_READY_MARKER)); + pump.waitUntilReady(); + writeLine("WARNING: Using incubator modules: jdk.incubator.vector and more stuff"); + writeLine("prefix WARNING: Using incubator modules: jdk.incubator.vector"); + closeAndDrain(); + assertThat(output(), containsString("and more stuff")); + assertThat(output(), containsString("prefix WARNING")); + } + + public void testMessagesBeforeMarkerPassThrough() throws Exception { + startPump(); + writeLine("early warning"); + writeLine(String.valueOf(ErrorPumpThread.SERVER_READY_MARKER)); + pump.waitUntilReady(); + closeAndDrain(); + assertThat(output(), containsString("early warning")); + } +} diff --git a/distribution/tools/server-launcher/src/test/java/org/elasticsearch/server/launcher/ServerLauncherTests.java b/distribution/tools/server-launcher/src/test/java/org/elasticsearch/server/launcher/ServerLauncherTests.java new file mode 100644 index 0000000000000..c91a81005e303 --- /dev/null +++ b/distribution/tools/server-launcher/src/test/java/org/elasticsearch/server/launcher/ServerLauncherTests.java @@ -0,0 +1,447 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.server.launcher; + +import org.elasticsearch.server.launcher.common.LaunchDescriptor; +import org.elasticsearch.server.launcher.common.ProcessUtil; +import org.elasticsearch.test.ESTestCase; +import org.junit.AfterClass; +import org.junit.Before; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.io.PrintStream; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasEntry; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.hasKey; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; + +/** + * Tests for {@link ServerLauncher} and implicitly {@link ServerProcess}. + * Uses an injectable process starter so no real subprocess is spawned. + */ +public class ServerLauncherTests extends ESTestCase { + + private static final ExecutorService MOCK_EXECUTOR = Executors.newSingleThreadExecutor(); + private static final long MOCK_PID = 12345L; + + private ServerLauncher launcher; + private Path workingDir; + private Path tempDir; + private ByteArrayOutputStream capturedStderr; + private PrintStream originalErr; + private volatile ServerProcess activeServer; + + @FunctionalInterface + private interface ServerBehavior { + void run(InputStream stdin, OutputStream stderr, AtomicInteger exitCode) throws IOException; + } + + /** + * A mock Process that uses pipes for stdin/stderr and a background thread + * that reads server args, writes the ready marker, then runs a configurable behavior. + */ + private static class MockServerProcess extends Process { + private final PipedOutputStream processStdin = new PipedOutputStream(); + private final PipedInputStream processStderr = new PipedInputStream(); + private final PipedInputStream stdin = new PipedInputStream(); + private final PipedOutputStream stderr = new PipedOutputStream(); + private final AtomicInteger exitCode = new AtomicInteger(0); + private final Future serverThread; + + MockServerProcess(LaunchDescriptor descriptor, ServerBehavior behavior) throws IOException { + stdin.connect(processStdin); + stderr.connect(processStderr); + int argsLen = descriptor.serverArgsBytes().length; + this.serverThread = MOCK_EXECUTOR.submit(() -> { + try { + byte[] buf = new byte[Math.max(1, argsLen)]; + int n = 0; + while (n < argsLen) { + int r = stdin.read(buf, n, argsLen - n); + if (r <= 0) break; + n += r; + } + try (PrintStream err = new PrintStream(stderr, true, StandardCharsets.UTF_8)) { + err.println(ErrorPumpThread.SERVER_READY_MARKER); + behavior.run(stdin, stderr, exitCode); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } finally { + try { + stdin.close(); + stderr.close(); + } catch (IOException ignored) {} + } + }); + } + + @Override + public OutputStream getOutputStream() { + return processStdin; + } + + @Override + public InputStream getInputStream() { + return InputStream.nullInputStream(); + } + + @Override + public InputStream getErrorStream() { + return processStderr; + } + + @Override + public long pid() { + return MOCK_PID; + } + + @Override + public int waitFor() throws InterruptedException { + try { + serverThread.get(); + } catch (ExecutionException e) { + throw new AssertionError("Mock server thread failed", e.getCause()); + } + return exitCode.get(); + } + + @Override + public int exitValue() { + if (serverThread.isDone() == false) { + throw new IllegalThreadStateException(); + } + return exitCode.get(); + } + + @Override + public void destroy() { + throw new UnsupportedOperationException("destroy not used in tests"); + } + + @Override + public Process destroyForcibly() { + serverThread.cancel(true); + return this; + } + } + + @AfterClass + public static void shutdownExecutor() { + MOCK_EXECUTOR.shutdown(); + } + + @Before + public void setUpTestDirs() throws Exception { + launcher = new ServerLauncher<>(); + workingDir = createTempDir(); + tempDir = createTempDir(); + capturedStderr = new ByteArrayOutputStream(); + originalErr = System.err; + System.setErr(new PrintStream(capturedStderr, true, StandardCharsets.UTF_8)); + } + + @Override + public void tearDown() throws Exception { + try { + ServerProcess server = activeServer; + if (server != null) { + activeServer = null; + server.stop(); + } + } finally { + try { + System.setErr(originalErr); + } finally { + super.tearDown(); + } + } + } + + private LaunchDescriptor descriptor( + String command, + List jvmOptions, + List jvmArgs, + Map environment, + boolean daemonize, + byte[] serverArgsBytes + ) { + return new LaunchDescriptor( + command, + jvmOptions != null ? jvmOptions : List.of(), + jvmArgs != null ? jvmArgs : List.of(), + environment != null ? environment : Map.of(), + workingDir.toString(), + tempDir.toString(), + daemonize, + serverArgsBytes != null ? serverArgsBytes : new byte[0] + ); + } + + private String getCapturedStderr() { + System.err.flush(); + return capturedStderr.toString(StandardCharsets.UTF_8); + } + + private static MockServerProcess createMock(LaunchDescriptor d, ServerBehavior behavior) { + try { + return new MockServerProcess(d, behavior); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private ServerProcess startServer(LaunchDescriptor d, Function processStarter) throws Exception { + ServerProcess server = launcher.startServer(d, processStarter); + activeServer = server; + return server; + } + + public void testProcessBuilder() throws Exception { + AtomicReference capturedPb = new AtomicReference<>(); + LaunchDescriptor d = descriptor("/usr/bin/java", List.of(), List.of(), Map.of(), false, new byte[0]); + ServerBehavior behavior = (stdin, stderr, exitCode) -> { + try (PrintStream err = new PrintStream(stderr, true, StandardCharsets.UTF_8)) { + err.println("stderr message"); + } + stdin.read(); + }; + ServerProcess server = startServer(d, pb -> { + capturedPb.set(pb); + return createMock(d, behavior); + }); + assertThat(capturedPb.get().redirectInput(), equalTo(ProcessBuilder.Redirect.PIPE)); + assertThat(capturedPb.get().redirectOutput(), equalTo(ProcessBuilder.Redirect.INHERIT)); + assertThat(capturedPb.get().redirectError(), equalTo(ProcessBuilder.Redirect.PIPE)); + assertThat(capturedPb.get().directory().toString(), equalTo(workingDir.toString())); + server.stop(); + assertThat(getCapturedStderr(), containsString("stderr message")); + } + + public void testPid() throws Exception { + LaunchDescriptor d = descriptor("/usr/bin/java", List.of(), List.of(), Map.of(), true, new byte[0]); + ServerBehavior behavior = (stdin, stderr, exitCode) -> stdin.read(); + ServerProcess server = startServer(d, pb -> createMock(d, behavior)); + assertThat(server.pid(), equalTo(MOCK_PID)); + server.stop(); + } + + public void testStartError() throws Exception { + LaunchDescriptor d = descriptor("/usr/bin/java", List.of(), List.of(), Map.of(), false, new byte[0]); + Exception e = expectThrows(UncheckedIOException.class, () -> startServer(d, pb -> { + throw new UncheckedIOException(new IOException("something went wrong")); + })); + assertThat(e.getCause().getMessage(), equalTo("something went wrong")); + } + + public void testEnvPassthrough() throws Exception { + ProcessBuilder[] capturedPb = new ProcessBuilder[1]; + LaunchDescriptor d = descriptor("/usr/bin/java", List.of(), List.of(), Map.of("MY_ENV", "foo"), false, new byte[0]); + ServerProcess server = startServer(d, pb -> { + capturedPb[0] = pb; + return createMock(d, (stdin, stderr, exitCode) -> stdin.read()); + }); + assertThat(capturedPb[0].environment(), hasEntry(equalTo("MY_ENV"), equalTo("foo"))); + server.stop(); + } + + public void testLibffiEnv() throws Exception { + Path libffiDir = createTempDir(); + ProcessBuilder[] capturedPb = new ProcessBuilder[1]; + LaunchDescriptor d = descriptor( + "/usr/bin/java", + List.of(), + List.of(), + Map.of("LIBFFI_TMPDIR", libffiDir.toString()), + false, + new byte[0] + ); + ServerProcess server = startServer(d, pb -> { + capturedPb[0] = pb; + return createMock(d, (stdin, stderr, exitCode) -> stdin.read()); + }); + assertThat(capturedPb[0].environment(), hasKey("LIBFFI_TMPDIR")); + assertThat(Files.exists(Path.of(capturedPb[0].environment().get("LIBFFI_TMPDIR"))), is(true)); + server.stop(); + } + + public void testEnvCleared() throws Exception { + ProcessBuilder[] capturedPb = new ProcessBuilder[1]; + LaunchDescriptor d = descriptor("/usr/bin/java", List.of(), List.of(), Map.of("SOME_VAR", "value"), false, new byte[0]); + ServerProcess server = startServer(d, pb -> { + capturedPb[0] = pb; + return createMock(d, (stdin, stderr, exitCode) -> stdin.read()); + }); + assertThat(capturedPb[0].environment(), hasEntry(equalTo("SOME_VAR"), equalTo("value"))); + assertThat(capturedPb[0].environment(), not(hasKey("ES_TMPDIR"))); + assertThat(capturedPb[0].environment(), not(hasKey("ES_JAVA_OPTS"))); + server.stop(); + } + + public void testCommandLineSysprops() throws Exception { + ProcessBuilder[] capturedPb = new ProcessBuilder[1]; + LaunchDescriptor d = descriptor("/usr/bin/java", List.of("-Dfoo1=bar", "-Dfoo2=baz"), List.of(), Map.of(), false, new byte[0]); + ServerProcess server = startServer(d, pb -> { + capturedPb[0] = pb; + return createMock(d, (stdin, stderr, exitCode) -> stdin.read()); + }); + assertThat(capturedPb[0].command(), hasItems("-Dfoo1=bar", "-Dfoo2=baz")); + server.stop(); + } + + public void testCommandLine() throws Exception { + String mainClass = "org.elasticsearch.server/org.elasticsearch.bootstrap.Elasticsearch"; + String modulePath = workingDir.resolve("lib").toString(); + ProcessBuilder[] capturedPb = new ProcessBuilder[1]; + LaunchDescriptor d = descriptor( + workingDir.resolve("bin/java").toString(), + List.of(), + List.of("--module-path", modulePath, "-m", mainClass), + Map.of(), + false, + new byte[0] + ); + ServerProcess server = startServer(d, pb -> { + capturedPb[0] = pb; + return createMock(d, (stdin, stderr, exitCode) -> stdin.read()); + }); + assertThat(capturedPb[0].command(), hasItems("--module-path", modulePath, "-m", mainClass)); + server.stop(); + } + + public void testDetach() throws Exception { + LaunchDescriptor d = descriptor("/usr/bin/java", List.of(), List.of(), Map.of(), true, new byte[0]); + AtomicReference mockRef = new AtomicReference<>(); + ServerBehavior behavior = (stdin, stderr, exitCode) -> { + try (PrintStream err = new PrintStream(stderr, true, StandardCharsets.UTF_8)) { + err.println("final message"); + } + assertThat(stdin.read(), equalTo(-1)); + }; + ServerProcess server = startServer(d, pb -> { + mockRef.set(createMock(d, behavior)); + return mockRef.get(); + }); + server.detach(); + assertThat(getCapturedStderr(), containsString("final message")); + server.stop(); + ProcessUtil.nonInterruptible(() -> mockRef.get().waitFor()); + } + + public void testStop() throws Exception { + CountDownLatch mainReady = new CountDownLatch(1); + LaunchDescriptor d = descriptor("/usr/bin/java", List.of(), List.of(), Map.of(), false, new byte[0]); + ServerBehavior behavior = (stdin, stderr, exitCode) -> { + ProcessUtil.nonInterruptibleVoid(mainReady::await); + try (PrintStream err = new PrintStream(stderr, true, StandardCharsets.UTF_8)) { + err.println("final message"); + } + int b = stdin.read(); + assertThat(b, equalTo((int) ServerProcess.SERVER_SHUTDOWN_MARKER)); + }; + MockServerProcess mock = createMock(d, behavior); + ServerProcess server = startServer(d, pb -> mock); + mainReady.countDown(); + server.stop(); + assertThat(mock.serverThread.isDone(), is(true)); + assertThat(getCapturedStderr(), containsString("final message")); + } + + public void testWaitFor() throws Exception { + CountDownLatch mainReady = new CountDownLatch(1); + LaunchDescriptor d = descriptor("/usr/bin/java", List.of(), List.of(), Map.of(), false, new byte[0]); + ServerBehavior behavior = (stdin, stderr, exitCode) -> { + mainReady.countDown(); + assertThat(stdin.read(), equalTo((int) ServerProcess.SERVER_SHUTDOWN_MARKER)); + try (PrintStream err = new PrintStream(stderr, true, StandardCharsets.UTF_8)) { + err.println("final message"); + } + }; + MockServerProcess mock = createMock(d, behavior); + ServerProcess server = startServer(d, pb -> mock); + CompletableFuture exitFuture = CompletableFuture.supplyAsync(() -> { + ProcessUtil.nonInterruptibleVoid(mainReady::await); + try { + server.stop(); + return 0; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + int exitCode = server.waitFor(); + assertThat(exitCode, equalTo(0)); + assertThat(mock.serverThread.isDone(), is(true)); + assertThat(getCapturedStderr(), containsString("final message")); + exitFuture.get(); + } + + public void testProcessDies() throws Exception { + CountDownLatch mainExit = new CountDownLatch(1); + LaunchDescriptor d = descriptor("/usr/bin/java", List.of(), List.of(), Map.of(), false, new byte[0]); + ServerBehavior behavior = (stdin, stderr, exitCode) -> { + try (PrintStream err = new PrintStream(stderr, true, StandardCharsets.UTF_8)) { + err.println("fatal message"); + } + ProcessUtil.nonInterruptibleVoid(mainExit::await); + exitCode.set(-9); + }; + MockServerProcess mock = createMock(d, behavior); + ServerProcess server = startServer(d, pb -> mock); + mainExit.countDown(); + int exitCode = server.waitFor(); + assertThat(exitCode, equalTo(-9)); + } + + public void testLogsDirCreateParents() throws Exception { + Path testDir = createTempDir(); + Path logsDir = testDir.resolve("subdir/logs"); + ProcessBuilder[] capturedPb = new ProcessBuilder[1]; + LaunchDescriptor d = new LaunchDescriptor( + "/usr/bin/java", + List.of(), + List.of(), + Map.of(), + logsDir.toString(), + tempDir.toString(), + false, + new byte[0] + ); + ServerProcess server = startServer(d, pb -> { + capturedPb[0] = pb; + return createMock(d, (stdin, stderr, exitCode) -> stdin.read()); + }); + assertThat(capturedPb[0].directory().toString(), equalTo(logsDir.toString())); + server.stop(); + } +} diff --git a/distribution/tools/windows-service-cli/build.gradle b/distribution/tools/windows-service-cli/build.gradle index dcfaf244b7eec..2d090fc4a8af8 100644 --- a/distribution/tools/windows-service-cli/build.gradle +++ b/distribution/tools/windows-service-cli/build.gradle @@ -4,6 +4,8 @@ dependencies { compileOnly project(":server") compileOnly project(":libs:cli") compileOnly project(":distribution:tools:server-cli") + compileOnly project(":distribution:tools:server-launcher") + compileOnly project(":libs:server-launcher-common") testImplementation project(":test:framework") } diff --git a/distribution/tools/windows-service-cli/src/main/java/org/elasticsearch/windows/service/WindowsServiceDaemon.java b/distribution/tools/windows-service-cli/src/main/java/org/elasticsearch/windows/service/WindowsServiceDaemon.java index 2854d76c110d1..8484f222c00ea 100644 --- a/distribution/tools/windows-service-cli/src/main/java/org/elasticsearch/windows/service/WindowsServiceDaemon.java +++ b/distribution/tools/windows-service-cli/src/main/java/org/elasticsearch/windows/service/WindowsServiceDaemon.java @@ -14,17 +14,28 @@ import org.elasticsearch.bootstrap.ServerArgs; import org.elasticsearch.cli.ProcessInfo; import org.elasticsearch.cli.Terminal; +import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.cli.EnvironmentAwareCommand; +import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.settings.KeyStoreWrapper; import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.env.Environment; import org.elasticsearch.server.cli.JvmOptionsParser; import org.elasticsearch.server.cli.MachineDependentHeap; -import org.elasticsearch.server.cli.ServerProcess; -import org.elasticsearch.server.cli.ServerProcessBuilder; import org.elasticsearch.server.cli.ServerProcessUtils; +import org.elasticsearch.server.launcher.ErrorPumpThread; +import org.elasticsearch.server.launcher.ServerProcess; +import java.io.File; import java.io.IOException; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Starts an Elasticsearch process, but does not wait for it to exit. @@ -47,16 +58,111 @@ public void execute(Terminal terminal, OptionSet options, Environment env, Proce var args = new ServerArgs(false, true, null, loadedSecrets, env.settings(), env.configDir(), env.logsDir()); var tempDir = ServerProcessUtils.setupTempDir(processInfo); var jvmOptions = JvmOptionsParser.determineJvmOptions(args, processInfo, tempDir, new MachineDependentHeap()); - var serverProcessBuilder = new ServerProcessBuilder().withTerminal(terminal) - .withProcessInfo(processInfo) - .withServerArgs(args) - .withTempDir(tempDir) - .withJvmOptions(jvmOptions); - this.server = serverProcessBuilder.start(); + + String command = getJavaCommand(processInfo); + List jvmArgs = getJvmArgs(processInfo); + Map environment = getEnvironment(processInfo, tempDir); + byte[] serverArgsBytes = serializeServerArgs(args); + + this.server = startServer(command, jvmOptions, jvmArgs, environment, args.logsDir(), serverArgsBytes); // start does not return until the server is ready, and we do not wait for the process } } + private static ServerProcess startServer( + String command, + List jvmOptions, + List jvmArgs, + Map environment, + Path workingDir, + byte[] serverArgsBytes + ) throws Exception { + Files.createDirectories(workingDir); + + List cmd = new ArrayList<>(); + cmd.add(command); + cmd.addAll(jvmOptions); + cmd.addAll(jvmArgs); + + ProcessBuilder pb = new ProcessBuilder(cmd); + pb.environment().clear(); + pb.environment().putAll(environment); + pb.directory(new File(workingDir.toString())); + pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); + + Process jvmProcess = null; + ErrorPumpThread errorPump; + boolean success = false; + + try { + jvmProcess = pb.start(); + errorPump = new ErrorPumpThread(jvmProcess.getErrorStream(), System.err); + errorPump.start(); + sendServerArgs(serverArgsBytes, jvmProcess.getOutputStream()); + + boolean serverOk = errorPump.waitUntilReady(); + if (serverOk == false) { + int exitCode = jvmProcess.waitFor(); + throw new RuntimeException("Elasticsearch died while starting up, exit code: " + exitCode); + } + success = true; + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new UncheckedIOException(e); + } finally { + if (success == false && jvmProcess != null && jvmProcess.isAlive()) { + jvmProcess.destroyForcibly(); + } + } + + return new ServerProcess(jvmProcess, errorPump); + } + + private static String getJavaCommand(ProcessInfo processInfo) { + Path javaHome = Path.of(processInfo.sysprops().get("java.home")); + return javaHome.resolve("bin").resolve("java.exe").toString(); + } + + private static List getJvmArgs(ProcessInfo processInfo) { + Path esHome = processInfo.workingDir(); + return List.of( + "--module-path", + esHome.resolve("lib").toString(), + "--add-modules=jdk.net", + "--add-modules=jdk.management.agent", + "--add-modules=ALL-MODULE-PATH", + "-m", + "org.elasticsearch.server/org.elasticsearch.bootstrap.Elasticsearch" + ); + } + + private static Map getEnvironment(ProcessInfo processInfo, Path tempDir) { + Map envVars = new HashMap<>(processInfo.envVars()); + envVars.remove("ES_TMPDIR"); + if (envVars.containsKey("LIBFFI_TMPDIR") == false) { + envVars.put("LIBFFI_TMPDIR", tempDir.toString()); + } + envVars.remove("ES_JAVA_OPTS"); + return envVars; + } + + private static byte[] serializeServerArgs(ServerArgs args) throws IOException { + try (BytesStreamOutput out = new BytesStreamOutput()) { + args.writeTo(out); + return BytesReference.toBytes(out.bytes()); + } + } + + private static void sendServerArgs(byte[] serverArgsBytes, OutputStream processStdin) { + try { + processStdin.write(serverArgsBytes); + processStdin.flush(); + } catch (IOException ignore) { + // A failure to write here means the process has problems, and it will die anyway. + } + } + @Override public void close() throws IOException { if (server != null) { diff --git a/distribution/tools/windows-service-cli/src/main/java/org/elasticsearch/windows/service/WindowsServiceInstallCommand.java b/distribution/tools/windows-service-cli/src/main/java/org/elasticsearch/windows/service/WindowsServiceInstallCommand.java index 75f508ad21499..af233f3e7c325 100644 --- a/distribution/tools/windows-service-cli/src/main/java/org/elasticsearch/windows/service/WindowsServiceInstallCommand.java +++ b/distribution/tools/windows-service-cli/src/main/java/org/elasticsearch/windows/service/WindowsServiceInstallCommand.java @@ -64,7 +64,7 @@ protected String getAdditionalArgs(String serviceId, ProcessInfo pinfo) { addArg(args, "--StopMode", "jvm"); addQuotedArg(args, "--StartPath", quote(pinfo.workingDir().toString())); addArg(args, "++JvmOptions", "-Dcli.name=windows-service-daemon"); - addArg(args, "++JvmOptions", "-Dcli.libs=lib/tools/server-cli,lib/tools/windows-service-cli"); + addArg(args, "++JvmOptions", "-Dcli.libs=lib/tools/server-cli,lib/tools/server-launcher,lib/tools/windows-service-cli"); addArg(args, "++Environment", String.format(java.util.Locale.ROOT, "HOSTNAME=%s", pinfo.envVars().get("COMPUTERNAME"))); String serviceUsername = pinfo.envVars().get("SERVICE_USERNAME"); diff --git a/distribution/tools/windows-service-cli/src/test/java/org/elasticsearch/windows/service/WindowsServiceInstallCommandTests.java b/distribution/tools/windows-service-cli/src/test/java/org/elasticsearch/windows/service/WindowsServiceInstallCommandTests.java index 4d3d6400c55c4..26e6fffc4424c 100644 --- a/distribution/tools/windows-service-cli/src/test/java/org/elasticsearch/windows/service/WindowsServiceInstallCommandTests.java +++ b/distribution/tools/windows-service-cli/src/test/java/org/elasticsearch/windows/service/WindowsServiceInstallCommandTests.java @@ -111,7 +111,7 @@ public void testJvmOptions() throws Exception { options, containsInAnyOrder( "-Dcli.name=windows-service-daemon", - "-Dcli.libs=lib/tools/server-cli,lib/tools/windows-service-cli", + "-Dcli.libs=lib/tools/server-cli,lib/tools/server-launcher,lib/tools/windows-service-cli", String.join(";", expectedOptions) ) ); diff --git a/libs/server-launcher-common/build.gradle b/libs/server-launcher-common/build.gradle new file mode 100644 index 0000000000000..1d60e53bc7e55 --- /dev/null +++ b/libs/server-launcher-common/build.gradle @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ +apply plugin: 'elasticsearch.build' + +// This library has zero ES dependencies - only JDK classes +dependencies { + testImplementation(project(":test:framework")) +} + +// Since this library does not depend on :server, it cannot run the jarHell task +tasks.named("jarHell").configure { enabled = false } + +tasks.named('forbiddenApisMain').configure { + replaceSignatureFiles 'jdk-signatures' +} + +["javadoc", "loggerUsageCheck"].each { tsk -> + tasks.named(tsk).configure { enabled = false } +} diff --git a/libs/server-launcher-common/src/main/java/org/elasticsearch/server/launcher/common/LaunchDescriptor.java b/libs/server-launcher-common/src/main/java/org/elasticsearch/server/launcher/common/LaunchDescriptor.java new file mode 100644 index 0000000000000..2abdb83a375c5 --- /dev/null +++ b/libs/server-launcher-common/src/main/java/org/elasticsearch/server/launcher/common/LaunchDescriptor.java @@ -0,0 +1,311 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.server.launcher.common; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Holds all the information needed by the launcher to spawn the Elasticsearch server process. + *

    + * This class is serialized to a binary format by the preparer (server-cli) and deserialized + * by the launcher (server-launcher). It uses only JDK classes so that the launcher has no + * Elasticsearch dependencies. + *

    + * Subclasses (e.g. {@code ServerlessLaunchDescriptor}) can extend this class and use + * {@link #writeFieldsTo(DataOutputStream)} / {@link #readFieldsFrom(DataInputStream)} + * to serialize/deserialize base fields without the magic number prefix. + */ +public class LaunchDescriptor { + + public static final String DESCRIPTOR_FILENAME = "launch-descriptor.bin"; + + private static final int MAGIC = 0x45534C44; // "ESLD" - ElasticSearch Launch Descriptor + + private final String command; + private final List jvmOptions; + private final List jvmArgs; + private final Map environment; + private final String workingDir; + private final String tempDir; + private final boolean daemonize; + private final byte[] serverArgsBytes; + + public LaunchDescriptor( + String command, + List jvmOptions, + List jvmArgs, + Map environment, + String workingDir, + String tempDir, + boolean daemonize, + byte[] serverArgsBytes + ) { + this.command = command; + this.jvmOptions = List.copyOf(jvmOptions); + this.jvmArgs = List.copyOf(jvmArgs); + this.environment = Map.copyOf(environment); + this.workingDir = workingDir; + this.tempDir = tempDir; + this.daemonize = daemonize; + this.serverArgsBytes = serverArgsBytes.clone(); + } + + /** + * Copy constructor for use by subclasses. + */ + protected LaunchDescriptor(LaunchDescriptor other) { + this.command = other.command; + this.jvmOptions = other.jvmOptions; + this.jvmArgs = other.jvmArgs; + this.environment = other.environment; + this.workingDir = other.workingDir; + this.tempDir = other.tempDir; + this.daemonize = other.daemonize; + this.serverArgsBytes = other.serverArgsBytes; + } + + public String command() { + return command; + } + + public List jvmOptions() { + return jvmOptions; + } + + public List jvmArgs() { + return jvmArgs; + } + + public Map environment() { + return environment; + } + + public String workingDir() { + return workingDir; + } + + public String tempDir() { + return tempDir; + } + + public boolean daemonize() { + return daemonize; + } + + public byte[] serverArgsBytes() { + return serverArgsBytes; + } + + /** + * Writes this descriptor to a binary file. + */ + public void writeTo(Path path) throws IOException { + try (OutputStream fos = Files.newOutputStream(path); DataOutputStream out = new DataOutputStream(fos)) { + writeTo(out); + } + } + + /** + * Writes this descriptor to a DataOutputStream, including the magic number prefix. + */ + public void writeTo(DataOutputStream out) throws IOException { + out.writeInt(MAGIC); + writeFieldsTo(out); + out.flush(); + } + + /** + * Writes the fields of this descriptor without the magic number prefix. + * Subclasses can call this to embed base fields in their own wire format. + */ + protected void writeFieldsTo(DataOutputStream out) throws IOException { + out.writeUTF(command); + writeStringList(out, jvmOptions); + writeStringList(out, jvmArgs); + writeStringMap(out, environment); + out.writeUTF(workingDir); + out.writeUTF(tempDir); + out.writeBoolean(daemonize); + out.writeInt(serverArgsBytes.length); + out.write(serverArgsBytes); + } + + /** + * Reads a descriptor from a binary file. + */ + public static LaunchDescriptor readFrom(Path path) throws IOException { + try (InputStream fis = Files.newInputStream(path); DataInputStream in = new DataInputStream(fis)) { + return readFrom(in); + } + } + + /** + * Reads a descriptor from a DataInputStream, checking the magic number prefix. + */ + public static LaunchDescriptor readFrom(DataInputStream in) throws IOException { + checkMagic(in, MAGIC); + return readFieldsFrom(in); + } + + /** + * Reads descriptor fields without the magic number prefix. + * Subclasses can call this to read base fields from their own wire format. + */ + protected static LaunchDescriptor readFieldsFrom(DataInputStream in) throws IOException { + String command = in.readUTF(); + List jvmOptions = readStringList(in); + List jvmArgs = readStringList(in); + Map environment = readStringMap(in); + String workingDir = in.readUTF(); + String tempDir = in.readUTF(); + boolean daemonize = in.readBoolean(); + int serverArgsBytesLen = in.readInt(); + byte[] serverArgsBytes = in.readNBytes(serverArgsBytesLen); + if (serverArgsBytes.length != serverArgsBytesLen) { + throw new IOException("Truncated server args: expected " + serverArgsBytesLen + " bytes, got " + serverArgsBytes.length); + } + + return new LaunchDescriptor(command, jvmOptions, jvmArgs, environment, workingDir, tempDir, daemonize, serverArgsBytes); + } + + /** + * Checks the magic number from the stream and throws if it doesn't match. + */ + protected static void checkMagic(DataInputStream in, int expectedMagic) throws IOException { + int magic = in.readInt(); + if (magic != expectedMagic) { + throw new IOException("Invalid launch descriptor: bad magic number"); + } + } + + /** + * Returns a human-readable representation of this descriptor in a section-based text format. + * Useful for debugging with the launcher's --dump flag. + */ + public String toHumanReadable() { + StringBuilder sb = new StringBuilder(); + + appendSection(sb, "command", command); + appendSection(sb, "working_dir", workingDir); + appendSection(sb, "temp_dir", tempDir); + appendSection(sb, "daemonize", String.valueOf(daemonize)); + appendSection(sb, "server_args_bytes", "<" + serverArgsBytes.length + " bytes>"); + + sb.append("[jvm_options]\n"); + for (String opt : jvmOptions) { + sb.append(opt).append('\n'); + } + sb.append('\n'); + + sb.append("[jvm_args]\n"); + for (String arg : jvmArgs) { + sb.append(arg).append('\n'); + } + sb.append('\n'); + + sb.append("[environment]\n"); + for (Map.Entry entry : environment.entrySet()) { + sb.append(entry.getKey()).append('=').append(entry.getValue()).append('\n'); + } + + return sb.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + LaunchDescriptor that = (LaunchDescriptor) o; + return daemonize == that.daemonize + && Objects.equals(command, that.command) + && Objects.equals(jvmOptions, that.jvmOptions) + && Objects.equals(jvmArgs, that.jvmArgs) + && Objects.equals(environment, that.environment) + && Objects.equals(workingDir, that.workingDir) + && Objects.equals(tempDir, that.tempDir) + && Arrays.equals(serverArgsBytes, that.serverArgsBytes); + } + + @Override + public int hashCode() { + int result = Objects.hash(command, jvmOptions, jvmArgs, environment, workingDir, tempDir, daemonize); + result = 31 * result + Arrays.hashCode(serverArgsBytes); + return result; + } + + @Override + public String toString() { + return "LaunchDescriptor{command='" + command + "', workingDir='" + workingDir + "', daemonize=" + daemonize + "}"; + } + + protected static void writeNullableString(DataOutputStream out, String value) throws IOException { + out.writeBoolean(value != null); + if (value != null) { + out.writeUTF(value); + } + } + + protected static String readNullableString(DataInputStream in) throws IOException { + boolean present = in.readBoolean(); + return present ? in.readUTF() : null; + } + + private static void appendSection(StringBuilder sb, String name, String value) { + sb.append('[').append(name).append("]\n"); + sb.append(value).append("\n\n"); + } + + private static void writeStringList(DataOutputStream out, List list) throws IOException { + out.writeInt(list.size()); + for (String s : list) { + out.writeUTF(s); + } + } + + private static List readStringList(DataInputStream in) throws IOException { + int size = in.readInt(); + List list = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + list.add(in.readUTF()); + } + return list; + } + + private static void writeStringMap(DataOutputStream out, Map map) throws IOException { + out.writeInt(map.size()); + for (Map.Entry entry : map.entrySet()) { + out.writeUTF(entry.getKey()); + out.writeUTF(entry.getValue()); + } + } + + private static Map readStringMap(DataInputStream in) throws IOException { + int size = in.readInt(); + Map map = new LinkedHashMap<>(size); + for (int i = 0; i < size; i++) { + String key = in.readUTF(); + String value = in.readUTF(); + map.put(key, value); + } + return map; + } +} diff --git a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ProcessUtil.java b/libs/server-launcher-common/src/main/java/org/elasticsearch/server/launcher/common/ProcessUtil.java similarity index 69% rename from distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ProcessUtil.java rename to libs/server-launcher-common/src/main/java/org/elasticsearch/server/launcher/common/ProcessUtil.java index 9564bdd8aa557..0d678abefd4b0 100644 --- a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ProcessUtil.java +++ b/libs/server-launcher-common/src/main/java/org/elasticsearch/server/launcher/common/ProcessUtil.java @@ -7,17 +7,20 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.server.cli; +package org.elasticsearch.server.launcher.common; -class ProcessUtil { +/** + * Utility methods for dealing with interruptible operations in a no-interruption-policy context. + */ +public class ProcessUtil { - private ProcessUtil() { /* no instance*/ } + private ProcessUtil() { /* no instance */ } - interface Interruptible { + public interface Interruptible { T run() throws InterruptedException; } - interface InterruptibleVoid { + public interface InterruptibleVoid { void run() throws InterruptedException; } @@ -26,7 +29,7 @@ interface InterruptibleVoid { * * This is useful for threads which expect a no interruption policy */ - static T nonInterruptible(Interruptible interruptible) { + public static T nonInterruptible(Interruptible interruptible) { try { return interruptible.run(); } catch (InterruptedException e) { @@ -35,7 +38,7 @@ static T nonInterruptible(Interruptible interruptible) { } } - static void nonInterruptibleVoid(InterruptibleVoid interruptible) { + public static void nonInterruptibleVoid(InterruptibleVoid interruptible) { nonInterruptible(() -> { interruptible.run(); return null; diff --git a/libs/server-launcher-common/src/test/java/org/elasticsearch/server/launcher/common/LaunchDescriptorTests.java b/libs/server-launcher-common/src/test/java/org/elasticsearch/server/launcher/common/LaunchDescriptorTests.java new file mode 100644 index 0000000000000..10e7e62f30f35 --- /dev/null +++ b/libs/server-launcher-common/src/test/java/org/elasticsearch/server/launcher/common/LaunchDescriptorTests.java @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.server.launcher.common; + +import org.elasticsearch.test.ESTestCase; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasToString; + +public class LaunchDescriptorTests extends ESTestCase { + + /** + * Round-trip via DataOutputStream/DataInputStream: write descriptor to bytes, read back, assert all fields match. + */ + public void testRoundTripViaStreams() throws IOException { + LaunchDescriptor original = descriptorWithSampleData(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (DataOutputStream out = new DataOutputStream(baos)) { + original.writeTo(out); + } + LaunchDescriptor readBack; + try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()))) { + readBack = LaunchDescriptor.readFrom(in); + } + assertDescriptorEquals(original, readBack); + } + + /** + * Round-trip via Path: write descriptor to a temp file, read back, assert all fields match. + */ + public void testRoundTripViaPath() throws IOException { + LaunchDescriptor original = descriptorWithSampleData(); + Path path = createTempDir().resolve(LaunchDescriptor.DESCRIPTOR_FILENAME); + original.writeTo(path); + LaunchDescriptor readBack = LaunchDescriptor.readFrom(path); + assertDescriptorEquals(original, readBack); + } + + /** + * Minimal descriptor with empty lists, empty map, and small server args round-trips correctly. + */ + public void testRoundTripMinimalDescriptor() throws IOException { + LaunchDescriptor original = new LaunchDescriptor( + "/usr/bin/java", + List.of(), + List.of(), + Map.of(), + "/var/log/elasticsearch", + "/tmp/elasticsearch", + false, + new byte[] { 0x00, 0x01 } + ); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (DataOutputStream out = new DataOutputStream(baos)) { + original.writeTo(out); + } + try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()))) { + LaunchDescriptor readBack = LaunchDescriptor.readFrom(in); + assertDescriptorEquals(original, readBack); + } + } + + /** + * Reading from a stream with wrong magic number throws IOException with a clear message. + */ + public void testInvalidMagicThrows() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (DataOutputStream out = new DataOutputStream(baos)) { + out.writeInt(0xDEADBEEF); + out.writeUTF("/usr/bin/java"); + } + try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()))) { + IOException e = expectThrows(IOException.class, () -> LaunchDescriptor.readFrom(in)); + assertThat(e, hasToString(containsString("bad magic number"))); + } + } + + private static LaunchDescriptor descriptorWithSampleData() { + return new LaunchDescriptor( + "/opt/elasticsearch/jdk/bin/java", + List.of("-Xms1g", "-Xmx1g", "-XX:+UseG1GC"), + List.of("--module-path", "/opt/elasticsearch/lib", "-m", "org.elasticsearch.server/org.elasticsearch.bootstrap.Elasticsearch"), + Map.of("ES_PATH_CONF", "/etc/elasticsearch", "ES_JAVA_OPTS", ""), + "/var/log/elasticsearch", + "/tmp/elasticsearch-12345", + true, + new byte[] { 1, 2, 3, 4, 5 } + ); + } + + private static void assertDescriptorEquals(LaunchDescriptor expected, LaunchDescriptor actual) { + assertThat(actual.command(), equalTo(expected.command())); + assertThat(actual.jvmOptions(), equalTo(expected.jvmOptions())); + assertThat(actual.jvmArgs(), equalTo(expected.jvmArgs())); + assertThat(actual.environment(), equalTo(expected.environment())); + assertThat(actual.workingDir(), equalTo(expected.workingDir())); + assertThat(actual.tempDir(), equalTo(expected.tempDir())); + assertThat(actual.daemonize(), equalTo(expected.daemonize())); + assertTrue("serverArgsBytes mismatch", Arrays.equals(expected.serverArgsBytes(), actual.serverArgsBytes())); + } +} diff --git a/qa/packaging/src/test/java/org/elasticsearch/packaging/test/ArchiveTests.java b/qa/packaging/src/test/java/org/elasticsearch/packaging/test/ArchiveTests.java index f444812a307fd..cf716b982fb4a 100644 --- a/qa/packaging/src/test/java/org/elasticsearch/packaging/test/ArchiveTests.java +++ b/qa/packaging/src/test/java/org/elasticsearch/packaging/test/ArchiveTests.java @@ -105,7 +105,7 @@ public void test32SpecialCharactersInJdkPath() throws Exception { mv(installation.bundledJdk, relocatedJdk); // ask for elasticsearch version to avoid starting the app final Result runResult = sh.run(bin.elasticsearch.toString() + " -V"); - assertThat(runResult.stdout(), startsWith("Version: ")); + assertThat(runResult.stderr(), startsWith("Version: ")); } finally { mv(relocatedJdk, installation.bundledJdk); } @@ -507,8 +507,8 @@ public void test74CustomJvmOptionsTotalMemoryOverride() throws Exception { final String nodesStatsResponse = makeRequest("https://localhost:9200/_nodes/stats"); assertThat(nodesStatsResponse, containsString("\"adjusted_total_in_bytes\":891289600")); final String nodesResponse = makeRequest("https://localhost:9200/_nodes"); - // 40% of (850MB - 100MB overhead) = 40% of 750MB - assertThat(nodesResponse, containsString("\"heap_init_in_bytes\":314572800")); + // 40% of 850MB + assertThat(nodesResponse, containsString("\"heap_init_in_bytes\":356515840")); stopElasticsearch(); } finally { diff --git a/qa/packaging/src/test/java/org/elasticsearch/packaging/test/DockerTests.java b/qa/packaging/src/test/java/org/elasticsearch/packaging/test/DockerTests.java index 7284182362ba5..901f21a4cda87 100644 --- a/qa/packaging/src/test/java/org/elasticsearch/packaging/test/DockerTests.java +++ b/qa/packaging/src/test/java/org/elasticsearch/packaging/test/DockerTests.java @@ -1031,8 +1031,8 @@ public void test140CgroupOsStatsAreAvailable() throws Exception { public void test150MachineDependentHeap() throws Exception { final List xArgs = machineDependentHeapTest("1536m", List.of()); - // This is roughly 0.5 * (1536 - 100) where 100 MB is the server-cli overhead - assertThat(xArgs, hasItems("-Xms718m", "-Xmx718m")); + // This is roughly 0.5 * 1536 + assertThat(xArgs, hasItems("-Xms768m", "-Xmx768m")); } /** @@ -1043,12 +1043,12 @@ public void test150MachineDependentHeap() throws Exception { public void test151MachineDependentHeapWithSizeOverride() throws Exception { final List xArgs = machineDependentHeapTest( "942m", - // 799014912 = 762m, 52428800 = 50m - List.of("-Des.total_memory_bytes=799014912", "-Des.total_memory_overhead_bytes=52428800") + // 799014912 = 762m + List.of("-Des.total_memory_bytes=799014912") ); - // This is roughly 0.4 * (762 - 50) - assertThat(xArgs, hasItems("-Xms284m", "-Xmx284m")); + // This is roughly 0.4 * 762, in particular it's NOT 0.4 * 942 + assertThat(xArgs, hasItems("-Xms304m", "-Xmx304m")); } private List machineDependentHeapTest(final String containerMemory, final List extraJvmOptions) throws Exception { diff --git a/qa/packaging/src/test/java/org/elasticsearch/packaging/test/KeystoreManagementTests.java b/qa/packaging/src/test/java/org/elasticsearch/packaging/test/KeystoreManagementTests.java index 13778e83ce5ff..d64fcea024c6e 100644 --- a/qa/packaging/src/test/java/org/elasticsearch/packaging/test/KeystoreManagementTests.java +++ b/qa/packaging/src/test/java/org/elasticsearch/packaging/test/KeystoreManagementTests.java @@ -173,7 +173,7 @@ public void test24EncryptedKeystoreAllowsHelpMessage() throws Exception { assertPasswordProtectedKeystore(); Shell.Result r = installation.executables().elasticsearch.run("--help"); - assertThat(r.stdout(), startsWith("Starts Elasticsearch")); + assertThat(r.stderr(), startsWith("Starts Elasticsearch")); } public void test30KeystorePasswordFromFile() throws Exception { diff --git a/qa/packaging/src/test/java/org/elasticsearch/packaging/test/PackageTests.java b/qa/packaging/src/test/java/org/elasticsearch/packaging/test/PackageTests.java index 24e86b967ee19..65cb241a69d77 100644 --- a/qa/packaging/src/test/java/org/elasticsearch/packaging/test/PackageTests.java +++ b/qa/packaging/src/test/java/org/elasticsearch/packaging/test/PackageTests.java @@ -258,8 +258,8 @@ public void test71JvmOptionsTotalMemoryOverride() throws Exception { final String nodesStatsResponse = makeRequest("https://localhost:9200/_nodes/stats"); assertThat(nodesStatsResponse, containsString("\"adjusted_total_in_bytes\":891289600")); - // 40% of (850MB - 100MB overhead) = 40% of 750MB - assertThat(sh.run("ps auwwx").stdout(), containsString("-Xms300m -Xmx300m")); + // 40% of 850MB + assertThat(sh.run("ps auwwx").stdout(), containsString("-Xms340m -Xmx340m")); stopElasticsearch(); }); diff --git a/qa/packaging/src/test/java/org/elasticsearch/packaging/util/Archives.java b/qa/packaging/src/test/java/org/elasticsearch/packaging/util/Archives.java index 69932ea34de5f..e9d4bfc1dc1e1 100644 --- a/qa/packaging/src/test/java/org/elasticsearch/packaging/util/Archives.java +++ b/qa/packaging/src/test/java/org/elasticsearch/packaging/util/Archives.java @@ -194,6 +194,13 @@ private static void verifyOssInstallation(Installation es, Distribution distribu Stream.of("NOTICE.txt", "LICENSE.txt", "README.asciidoc") .forEach(doc -> assertThat(es.home.resolve(doc), file(File, owner, owner, p644))); + + // Linux distributions (x86 and aarch64) include a native server-launcher binary; ensure it exists + // so we do not silently fall back to Java when the native image build was skipped or broken + if (distribution.platform == Distribution.Platform.LINUX) { + Path nativeLauncher = es.lib.resolve("tools").resolve("server-launcher").resolve("server-launcher"); + assertThat("native server-launcher must exist on Linux distribution", nativeLauncher, file(File, owner, owner, p755)); + } } private static void verifyDefaultInstallation(Installation es, Distribution distribution, String owner) { diff --git a/settings.gradle b/settings.gradle index 329b3571c2fbb..a28a619206c6a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -93,6 +93,7 @@ List projects = [ 'distribution:tools:java-version-checker', 'distribution:tools:cli-launcher', 'distribution:tools:server-cli', + 'distribution:tools:server-launcher', 'distribution:tools:windows-service-cli', 'distribution:tools:plugin-cli', 'distribution:tools:plugin-cli:bc', From 2424f85fc4a3a0a9592613497cc8a55bbf72c84b Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Sun, 15 Mar 2026 19:33:16 +0200 Subject: [PATCH 102/137] ESQL: Remove duplicates and cleanup orphans --- .../analysis/AnalyzerUnmappedGoldenTests.java | 26 -------------- .../testInlineStats/load/analysis.expected | 3 -- .../testInlineStats/load/query.esql | 2 -- .../testInlineStats/nullify/analysis.expected | 3 -- .../testInlineStats/nullify/query.esql | 2 -- .../nullify/analysis.expected | 35 ------------------- .../nullify/query.esql | 13 ------- 7 files changed, 84 deletions(-) delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/analysis.expected delete mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/query.esql diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java index 178c4d6c66d25..e3faf11ef4b5d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -211,13 +211,6 @@ public void testStatsMixedAndExpressions() throws Exception { """, STAGES); } - public void testInlineStats() throws Exception { - runTests(""" - FROM employees - | STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 - """); - } - public void testInlineStatsMixed() throws Exception { runTests(""" FROM employees @@ -607,25 +600,6 @@ public void testSubquerysMixAndLookupJoinNullify() throws Exception { """, STAGES); } - public void testSubquerysMixAndLookupJoinLoad() throws Exception { - assumeTrue("Requires subquery in FROM command support", EsqlCapabilities.Cap.SUBQUERY_IN_FROM_COMMAND.isEnabled()); - runTestsNullifyOnly(""" - FROM employees, - (FROM languages - | WHERE language_code > 10 - | RENAME language_name as languageName), - (FROM sample_data - | STATS max(@timestamp)), - (FROM employees - | EVAL language_code = languages - | LOOKUP JOIN languages_lookup ON language_code) - | WHERE emp_no > 10000 OR does_not_exist1::LONG < 10 - | STATS count(*) BY emp_no, language_code, does_not_exist2 - | RENAME emp_no AS empNo, language_code AS languageCode - | MV_EXPAND languageCode - """, STAGES); - } - public void testSubquerysWithMainAndStatsOnly() throws Exception { assumeTrue("Requires subquery in FROM command support", EsqlCapabilities.Cap.SUBQUERY_IN_FROM_COMMAND.isEnabled()); runTestsNullifyOnly(""" diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected deleted file mode 100644 index d8965ede4d87d..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0],[SUM(TODOUBLE(does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#1),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#2, does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0]] - \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist2{f(PotentiallyUnmappedKeywordEsField)}#0, does_not_exist1{f(PotentiallyUnmappedKeywordEsField)}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/query.esql deleted file mode 100644 index 4b45cf86d8cb5..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/load/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="load"; FROM employees -| STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected deleted file mode 100644 index 27b179dff2e21..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/analysis.expected +++ /dev/null @@ -1,3 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_Aggregate[[does_not_exist2{f}#0],[SUM(TODOUBLE(does_not_exist1{f}#1),true[BOOLEAN],PT0S[TIME_DURATION],compensated[KEYWORD]) AS s#2, does_not_exist2{f}#0]] - \_EsRelation[employees][avg_worked_seconds{f}#3, birth_date{f}#4, emp_no{f}#5, first_name{f}#6, gender{f}#7, height{f}#8, height.float{f}#9, height.half_float{f}#10, height.scaled_float{f}#11, hire_date{f}#12, is_rehired{f}#13, job_positions{f}#14, languages{f}#15, languages.byte{f}#16, languages.long{f}#17, languages.short{f}#18, last_name{f}#19, salary{f}#20, salary_change{f}#21, salary_change.int{f}#22, salary_change.keyword{f}#23, salary_change.long{f}#24, still_hired{f}#25, does_not_exist2{f}#0, does_not_exist1{f}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql deleted file mode 100644 index 29d53f6beba5b..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testInlineStats/nullify/query.esql +++ /dev/null @@ -1,2 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees -| STATS s = SUM(does_not_exist1::DOUBLE) BY does_not_exist2 diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/analysis.expected deleted file mode 100644 index 31dea66259d69..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/analysis.expected +++ /dev/null @@ -1,35 +0,0 @@ -Limit[1000[INTEGER],false,false] -\_MvExpand[languageCode{r}#0,languageCode{r}#1] - \_Project[[count(*){r}#2, emp_no{r}#3 AS empNo#4, language_code{r}#5 AS languageCode#0, does_not_exist2{r}#6]] - \_Aggregate[[emp_no{r}#3, language_code{r}#5, does_not_exist2{r}#6],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS count(*)#2, emp_no{r}#3, language_code{r}#5, does_not_exist2{r}#6]] - \_Filter[emp_no{r}#3 > 10000[INTEGER] OR $$does_not_exist1$converted_to$long{r$}#7 < 10[INTEGER]] - \_UnionAll[[avg_worked_seconds{r}#8, birth_date{r}#9, emp_no{r}#3, first_name{r}#10, gender{r}#11, height{r}#12, height.float{r}#13, height.half_float{r}#14, height.scaled_float{r}#15, hire_date{r}#16, is_rehired{r}#17, job_positions{r}#18, languages{r}#19, languages.byte{r}#20, languages.long{r}#21, languages.short{r}#22, last_name{r}#23, salary{r}#24, salary_change{r}#25, salary_change.int{r}#26, salary_change.keyword{r}#27, salary_change.long{r}#28, still_hired{r}#29, language_code{r}#5, languageName{r}#30, max(@timestamp){r}#31, language_name{r}#32, does_not_exist1{r}#33, $$does_not_exist1$converted_to$long{r$}#7, does_not_exist2{r}#6]] - |_Project[[avg_worked_seconds{f}#34, birth_date{f}#35, emp_no{f}#36, first_name{f}#37, gender{f}#38, height{f}#39, height.float{f}#40, height.half_float{f}#41, height.scaled_float{f}#42, hire_date{f}#43, is_rehired{f}#44, job_positions{f}#45, languages{f}#46, languages.byte{f}#47, languages.long{f}#48, languages.short{f}#49, last_name{f}#50, salary{f}#51, salary_change{f}#52, salary_change.int{f}#53, salary_change.keyword{f}#54, salary_change.long{f}#55, still_hired{f}#56, language_code{r}#57, languageName{r}#58, max(@timestamp){r}#59, language_name{r}#60, does_not_exist1{f}#61, $$does_not_exist1$converted_to$long{r$}#62, does_not_exist2{f}#63]] - | \_Eval[[TOLONG(does_not_exist1{f}#61) AS $$does_not_exist1$converted_to$long#62]] - | \_Eval[[null[INTEGER] AS language_code#57, null[KEYWORD] AS languageName#58, null[DATETIME] AS max(@timestamp)#59, null[KEYWORD] AS language_name#60]] - | \_EsRelation[employees][avg_worked_seconds{f}#34, birth_date{f}#35, emp_no{f}#36, first_name{f}#37, gender{f}#38, height{f}#39, height.float{f}#40, height.half_float{f}#41, height.scaled_float{f}#42, hire_date{f}#43, is_rehired{f}#44, job_positions{f}#45, languages{f}#46, languages.byte{f}#47, languages.long{f}#48, languages.short{f}#49, last_name{f}#50, salary{f}#51, salary_change{f}#52, salary_change.int{f}#53, salary_change.keyword{f}#54, salary_change.long{f}#55, still_hired{f}#56, does_not_exist1{f}#61, does_not_exist2{f}#63] - |_Project[[avg_worked_seconds{r}#64, birth_date{r}#65, emp_no{r}#66, first_name{r}#67, gender{r}#68, height{r}#69, height.float{r}#70, height.half_float{r}#71, height.scaled_float{r}#72, hire_date{r}#73, is_rehired{r}#74, job_positions{r}#75, languages{r}#76, languages.byte{r}#77, languages.long{r}#78, languages.short{r}#79, last_name{r}#80, salary{r}#81, salary_change{r}#82, salary_change.int{r}#83, salary_change.keyword{r}#84, salary_change.long{r}#85, still_hired{r}#86, language_code{f}#87, languageName{r}#88, max(@timestamp){r}#89, language_name{r}#90, does_not_exist1{f}#91, $$does_not_exist1$converted_to$long{r$}#92, does_not_exist2{f}#93]] - | \_Eval[[TOLONG(does_not_exist1{f}#91) AS $$does_not_exist1$converted_to$long#92]] - | \_Eval[[null[LONG] AS avg_worked_seconds#64, null[DATETIME] AS birth_date#65, null[INTEGER] AS emp_no#66, null[KEYWORD] AS first_name#67, null[KEYWORD] AS gender#68, null[DOUBLE] AS height#69, null[DOUBLE] AS height.float#70, null[DOUBLE] AS height.half_float#71, null[DOUBLE] AS height.scaled_float#72, null[DATETIME] AS hire_date#73, null[BOOLEAN] AS is_rehired#74, null[KEYWORD] AS job_positions#75, null[INTEGER] AS languages#76, null[INTEGER] AS languages.byte#77, null[LONG] AS languages.long#78, null[INTEGER] AS languages.short#79, null[KEYWORD] AS last_name#80, null[INTEGER] AS salary#81, null[DOUBLE] AS salary_change#82, null[INTEGER] AS salary_change.int#83, null[KEYWORD] AS salary_change.keyword#84, null[LONG] AS salary_change.long#85, null[BOOLEAN] AS still_hired#86, null[DATETIME] AS max(@timestamp)#89, null[KEYWORD] AS language_name#90]] - | \_Subquery[] - | \_Project[[language_code{f}#87, language_name{f}#94 AS languageName#88, does_not_exist1{f}#91, does_not_exist2{f}#93]] - | \_Filter[language_code{f}#87 > 10[INTEGER]] - | \_EsRelation[languages][language_code{f}#87, language_name{f}#94, does_not_exist1{f}#91, does_not_exist2{f}#93] - |_Project[[avg_worked_seconds{r}#95, birth_date{r}#96, emp_no{r}#97, first_name{r}#98, gender{r}#99, height{r}#100, height.float{r}#101, height.half_float{r}#102, height.scaled_float{r}#103, hire_date{r}#104, is_rehired{r}#105, job_positions{r}#106, languages{r}#107, languages.byte{r}#108, languages.long{r}#109, languages.short{r}#110, last_name{r}#111, salary{r}#112, salary_change{r}#113, salary_change.int{r}#114, salary_change.keyword{r}#115, salary_change.long{r}#116, still_hired{r}#117, language_code{r}#118, languageName{r}#119, max(@timestamp){r}#120, language_name{r}#121, does_not_exist1{r}#122, $$does_not_exist1$converted_to$long{r$}#123, does_not_exist2{r}#124]] - | \_Eval[[null[NULL] AS does_not_exist2#124]] - | \_Project[[avg_worked_seconds{r}#95, birth_date{r}#96, emp_no{r}#97, first_name{r}#98, gender{r}#99, height{r}#100, height.float{r}#101, height.half_float{r}#102, height.scaled_float{r}#103, hire_date{r}#104, is_rehired{r}#105, job_positions{r}#106, languages{r}#107, languages.byte{r}#108, languages.long{r}#109, languages.short{r}#110, last_name{r}#111, salary{r}#112, salary_change{r}#113, salary_change.int{r}#114, salary_change.keyword{r}#115, salary_change.long{r}#116, still_hired{r}#117, language_code{r}#118, languageName{r}#119, max(@timestamp){r}#120, language_name{r}#121, does_not_exist1{r}#122, $$does_not_exist1$converted_to$long{r$}#123]] - | \_Eval[[TOLONG(does_not_exist1{r}#122) AS $$does_not_exist1$converted_to$long#123]] - | \_Eval[[null[NULL] AS does_not_exist1#122]] - | \_Project[[avg_worked_seconds{r}#95, birth_date{r}#96, emp_no{r}#97, first_name{r}#98, gender{r}#99, height{r}#100, height.float{r}#101, height.half_float{r}#102, height.scaled_float{r}#103, hire_date{r}#104, is_rehired{r}#105, job_positions{r}#106, languages{r}#107, languages.byte{r}#108, languages.long{r}#109, languages.short{r}#110, last_name{r}#111, salary{r}#112, salary_change{r}#113, salary_change.int{r}#114, salary_change.keyword{r}#115, salary_change.long{r}#116, still_hired{r}#117, language_code{r}#118, languageName{r}#119, max(@timestamp){r}#120, language_name{r}#121]] - | \_Eval[[null[LONG] AS avg_worked_seconds#95, null[DATETIME] AS birth_date#96, null[INTEGER] AS emp_no#97, null[KEYWORD] AS first_name#98, null[KEYWORD] AS gender#99, null[DOUBLE] AS height#100, null[DOUBLE] AS height.float#101, null[DOUBLE] AS height.half_float#102, null[DOUBLE] AS height.scaled_float#103, null[DATETIME] AS hire_date#104, null[BOOLEAN] AS is_rehired#105, null[KEYWORD] AS job_positions#106, null[INTEGER] AS languages#107, null[INTEGER] AS languages.byte#108, null[LONG] AS languages.long#109, null[INTEGER] AS languages.short#110, null[KEYWORD] AS last_name#111, null[INTEGER] AS salary#112, null[DOUBLE] AS salary_change#113, null[INTEGER] AS salary_change.int#114, null[KEYWORD] AS salary_change.keyword#115, null[LONG] AS salary_change.long#116, null[BOOLEAN] AS still_hired#117, null[INTEGER] AS language_code#118, null[KEYWORD] AS languageName#119, null[KEYWORD] AS language_name#121]] - | \_Subquery[] - | \_Aggregate[[],[MAX(@timestamp{f}#125,true[BOOLEAN],PT0S[TIME_DURATION]) AS max(@timestamp)#120]] - | \_EsRelation[sample_data][@timestamp{f}#125, client_ip{f}#126, event_duration{f}#127, message{f}#128, does_not_exist1{f}#129, does_not_exist2{f}#130] - \_Project[[avg_worked_seconds{f}#131, birth_date{f}#132, emp_no{f}#133, first_name{f}#134, gender{f}#135, height{f}#136, height.float{f}#137, height.half_float{f}#138, height.scaled_float{f}#139, hire_date{f}#140, is_rehired{f}#141, job_positions{f}#142, languages{f}#143, languages.byte{f}#144, languages.long{f}#145, languages.short{f}#146, last_name{f}#147, salary{f}#148, salary_change{f}#149, salary_change.int{f}#150, salary_change.keyword{f}#151, salary_change.long{f}#152, still_hired{f}#153, language_code{r}#154, languageName{r}#155, max(@timestamp){r}#156, language_name{f}#157, does_not_exist1{f}#158, $$does_not_exist1$converted_to$long{r$}#159, does_not_exist2{f}#160]] - \_Eval[[TOLONG(does_not_exist1{f}#158) AS $$does_not_exist1$converted_to$long#159]] - \_Eval[[null[KEYWORD] AS languageName#155, null[DATETIME] AS max(@timestamp)#156]] - \_Subquery[] - \_LookupJoin[LEFT,[language_code{r}#154],[language_code{f}#161],false,null] - |_Eval[[languages{f}#143 AS language_code#154]] - | \_EsRelation[employees][avg_worked_seconds{f}#131, birth_date{f}#132, emp_no{f}#133, first_name{f}#134, gender{f}#135, height{f}#136, height.float{f}#137, height.half_float{f}#138, height.scaled_float{f}#139, hire_date{f}#140, is_rehired{f}#141, job_positions{f}#142, languages{f}#143, languages.byte{f}#144, languages.long{f}#145, languages.short{f}#146, last_name{f}#147, salary{f}#148, salary_change{f}#149, salary_change.int{f}#150, salary_change.keyword{f}#151, salary_change.long{f}#152, still_hired{f}#153, does_not_exist1{f}#158, does_not_exist2{f}#160] - \_EsRelation[languages_lookup][LOOKUP][language_code{f}#161, language_name{f}#157] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/query.esql deleted file mode 100644 index 17e10ed04b0eb..0000000000000 --- a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testSubquerysMixAndLookupJoinLoad/nullify/query.esql +++ /dev/null @@ -1,13 +0,0 @@ -SET unmapped_fields="nullify"; FROM employees, - (FROM languages - | WHERE language_code > 10 - | RENAME language_name as languageName), - (FROM sample_data - | STATS max(@timestamp)), - (FROM employees - | EVAL language_code = languages - | LOOKUP JOIN languages_lookup ON language_code) -| WHERE emp_no > 10000 OR does_not_exist1::LONG < 10 -| STATS count(*) BY emp_no, language_code, does_not_exist2 -| RENAME emp_no AS empNo, language_code AS languageCode -| MV_EXPAND languageCode From bfea2ff2e6c85e0d7e0a9b8d4f1bafbd8b21affe Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 17 Mar 2026 21:01:34 +0200 Subject: [PATCH 103/137] Re-add missing tests --- .../src/main/resources/unmapped-load.csv-spec | 207 ++++++++++++++++++ .../planner/EsPhysicalOperationProviders.java | 24 +- .../esql/planner/EsqlBlockLoaderContext.java | 17 +- 3 files changed, 245 insertions(+), 3 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index b97f728cb5c04..cd68078949cef 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -527,6 +527,213 @@ Connected to 10.1.0.1 42 ; +partiallyUnmappedNonKeyword +required_capability: optional_fields_v2 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL event_duration = event_duration::DOUBLE +| KEEP _index, event_duration +| SORT _index, event_duration +; + +_index:keyword | event_duration:double +no_mapping_sample_data | 725447.0 +no_mapping_sample_data | 1232381.0 +no_mapping_sample_data | 1756466.0 +no_mapping_sample_data | 2764888.0 +no_mapping_sample_data | 3450232.0 +no_mapping_sample_data | 5033754.0 +no_mapping_sample_data | 8268152.0 +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +; + +partiallyUnmappedNonKeywordNoExistence +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data, employees METADATA _index +| EVAL event_duration = event_duration::DOUBLE +| KEEP _index, event_duration +| SORT _index DESC, event_duration +| LIMIT 18 +; + +_index:keyword | event_duration:double +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +no_mapping_sample_data | 725447.0 +no_mapping_sample_data | 1232381.0 +no_mapping_sample_data | 1756466.0 +no_mapping_sample_data | 2764888.0 +no_mapping_sample_data | 3450232.0 +no_mapping_sample_data | 5033754.0 +no_mapping_sample_data | 8268152.0 +employees | null +employees | null +employees | null +employees | null +; + +partiallyUnmappedMixedTypes +required_capability: optional_fields_v2 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data, logs, no_mapping_sample_data METADATA _index +| EVAL message = message::KEYWORD, @timestamp = @timestamp :: date +| KEEP _index, @timestamp, message +| SORT _index, @timestamp DESC +; + +_index:keyword | @timestamp:date | message:keyword +logs | 2023-10-23T13:57:01.544Z | Running cats (cycle 3) +logs | 2023-10-23T13:56:01.544Z | Running cats (cycle 2) +logs | 2023-10-23T13:56:01.543Z | No response +logs | 2023-10-23T13:55:01.546Z | More java stuff +logs | 2023-10-23T13:55:01.545Z | Doing java stuff for 192.168.86.038 +logs | 2023-10-23T13:55:01.544Z | Running cats (cycle 1) +logs | 2023-10-23T13:55:01.543Z | Pinging 192.168.86.046 +no_mapping_sample_data | 2024-10-23T13:55:01.543Z | Connected to 10.1.0.1! +no_mapping_sample_data | 2024-10-23T13:53:55.832Z | Connection error? +no_mapping_sample_data | 2024-10-23T13:52:55.015Z | Connection error? +no_mapping_sample_data | 2024-10-23T13:51:54.732Z | Connection error? +no_mapping_sample_data | 2024-10-23T13:33:34.937Z | 42 +no_mapping_sample_data | 2024-10-23T12:27:28.948Z | Connected to 10.1.0.2! +no_mapping_sample_data | 2024-10-23T12:15:03.360Z | Connected to 10.1.0.3! +sample_data | 2023-10-23T13:55:01.543Z | Connected to 10.1.0.1 +sample_data | 2023-10-23T13:53:55.832Z | Connection error +sample_data | 2023-10-23T13:52:55.015Z | Connection error +sample_data | 2023-10-23T13:51:54.732Z | Connection error +sample_data | 2023-10-23T13:33:34.937Z | Disconnected +sample_data | 2023-10-23T12:27:28.948Z | Connected to 10.1.0.2 +sample_data | 2023-10-23T12:15:03.360Z | Connected to 10.1.0.3 +; + +####################### +# Type conflict tests # +####################### + +typeConflictKeywordUnmappedCastToKeyword +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL message = message::keyword +| KEEP _index, message +| SORT _index, message +; + +_index:keyword | message:keyword +no_mapping_sample_data | 42 +no_mapping_sample_data | Connected to 10.1.0.1! +no_mapping_sample_data | Connected to 10.1.0.2! +no_mapping_sample_data | Connected to 10.1.0.3! +no_mapping_sample_data | Connection error? +no_mapping_sample_data | Connection error? +no_mapping_sample_data | Connection error? +sample_data | Connected to 10.1.0.1 +sample_data | Connected to 10.1.0.2 +sample_data | Connected to 10.1.0.3 +sample_data | Connection error +sample_data | Connection error +sample_data | Connection error +sample_data | Disconnected +; + +typeConflictLongUnmappedCastToKeyword +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL event_duration = event_duration::keyword +| KEEP _index, event_duration +| SORT _index, event_duration +; + +_index:keyword | event_duration:keyword +no_mapping_sample_data | 1232381 +no_mapping_sample_data | 1756466 +no_mapping_sample_data | 2764888 +no_mapping_sample_data | 3450232 +no_mapping_sample_data | 5033754 +no_mapping_sample_data | 725447 +no_mapping_sample_data | 8268152 +sample_data | 1232382 +sample_data | 1756467 +sample_data | 2764889 +sample_data | 3450233 +sample_data | 5033755 +sample_data | 725448 +sample_data | 8268153 +; + +typeConflictLongUnmappedCastToLong +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL event_duration = event_duration::long +| KEEP _index, event_duration +| SORT _index, event_duration +; + +_index:keyword | event_duration:long +no_mapping_sample_data | 725447 +no_mapping_sample_data | 1232381 +no_mapping_sample_data | 1756466 +no_mapping_sample_data | 2764888 +no_mapping_sample_data | 3450232 +no_mapping_sample_data | 5033754 +no_mapping_sample_data | 8268152 +sample_data | 725448 +sample_data | 1232382 +sample_data | 1756467 +sample_data | 2764889 +sample_data | 3450233 +sample_data | 5033755 +sample_data | 8268153 +; + +typeConflictLongUnmappedCastToDouble +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL event_duration = event_duration::double +| KEEP _index, event_duration +| SORT _index, event_duration +; + +_index:keyword | event_duration:double +no_mapping_sample_data | 725447.0 +no_mapping_sample_data | 1232381.0 +no_mapping_sample_data | 1756466.0 +no_mapping_sample_data | 2764888.0 +no_mapping_sample_data | 3450232.0 +no_mapping_sample_data | 5033754.0 +no_mapping_sample_data | 8268152.0 +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +; + fieldIsPartiallyUnmappedPartiallySourceIsDisabledMultiIndex required_capability: optional_fields_v2 required_capability: source_field_mapping diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java index dd6a76379a229..d05be2cefbef8 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java @@ -84,6 +84,7 @@ import org.elasticsearch.xpack.esql.expression.function.BlockLoaderWarnings; import org.elasticsearch.xpack.esql.expression.function.blockloader.BlockLoaderExpression; import org.elasticsearch.xpack.esql.expression.function.scalar.EsqlScalarFunction; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; import org.elasticsearch.xpack.esql.plan.physical.EsQueryExec; import org.elasticsearch.xpack.esql.plan.physical.EsQueryExec.Sort; import org.elasticsearch.xpack.esql.plan.physical.EstimatesRowSize; @@ -259,7 +260,15 @@ private ValuesSourceReaderOperator.LoaderAndConverter blockLoaderAndConverter( String indexName = shardContext.ctx.getFullyQualifiedIndex().getName(); Expression conversion = unionTypes.getConversionExpressionForIndex(indexName); if (conversion == null) { - return ValuesSourceReaderOperator.LOAD_CONSTANT_NULLS; + Expression potentiallyUnmapped = unionTypes.getPotentiallyUnmappedExpression(); + if (potentiallyUnmapped != null && potentiallyUnmapped instanceof AbstractConvertFunction convert) { + String unmappedFieldName = ((FieldAttribute) convert.field()).fieldName().string(); + shardContext = wrapWithUnmappedFieldContext(shardContext, new PotentiallyUnmappedKeywordEsField(unmappedFieldName)); + conversion = potentiallyUnmapped; + fieldName = unmappedFieldName; + } else { + return ValuesSourceReaderOperator.LOAD_CONSTANT_NULLS; + } } if (conversion instanceof BlockLoaderExpression ble) { BlockLoaderExpression.PushedBlockLoaderExpression e = ble.tryPushToFieldLoading(SearchStats.EMPTY); @@ -315,6 +324,12 @@ private static class DefaultShardContextForUnmappedField extends DefaultShardCon return superResult == null && name.equals(unmappedEsField.getName()) ? createUnmappedFieldType(name, this) : superResult; } + @Override + protected Set resolveSourcePaths(String name) { + var result = super.resolveSourcePaths(name); + return result.isEmpty() && name.equals(unmappedEsField.getName()) ? Set.of(name) : result; + } + static MappedFieldType createUnmappedFieldType(String name, DefaultShardContext context) { var builder = new KeywordFieldMapper.Builder(name, context.ctx.getIndexSettings()); builder.docValues(false); @@ -624,7 +639,8 @@ public BlockLoader blockLoader( blockLoaderFunctionConfig, warnings, blockLoaderSizeOrdinals, - blockLoaderSizeScript + blockLoaderSizeScript, + this::resolveSourcePaths ) ); if (loader == null) { @@ -650,6 +666,10 @@ public double storedFieldsSequentialProportion() { return EsqlPlugin.STORED_FIELDS_SEQUENTIAL_PROPORTION.get(ctx.getIndexSettings().getSettings()); } + protected Set resolveSourcePaths(String name) { + return ctx.sourcePath(name); + } + @Override public void close() { releasable.close(); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsqlBlockLoaderContext.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsqlBlockLoaderContext.java index f7788e0acd05d..b215237cb51a8 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsqlBlockLoaderContext.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsqlBlockLoaderContext.java @@ -18,6 +18,7 @@ import org.elasticsearch.search.lookup.SearchLookup; import java.util.Set; +import java.util.function.Function; /** * {@link MappedFieldType.BlockLoaderContext} implementation for ESQL. @@ -29,6 +30,7 @@ class EsqlBlockLoaderContext implements MappedFieldType.BlockLoaderContext { private final Warnings warnings; private final ByteSizeValue blockLoaderSizeOrdinals; private final ByteSizeValue blockLoaderSizeScript; + private final Function> sourcePathResolver; EsqlBlockLoaderContext( SearchExecutionContext ctx, @@ -37,6 +39,18 @@ class EsqlBlockLoaderContext implements MappedFieldType.BlockLoaderContext { Warnings warnings, ByteSizeValue blockLoaderSizeOrdinals, ByteSizeValue blockLoaderSizeScript + ) { + this(ctx, fieldExtractPreference, blockLoaderFunctionConfig, warnings, blockLoaderSizeOrdinals, blockLoaderSizeScript, null); + } + + EsqlBlockLoaderContext( + SearchExecutionContext ctx, + MappedFieldType.FieldExtractPreference fieldExtractPreference, + BlockLoaderFunctionConfig blockLoaderFunctionConfig, + Warnings warnings, + ByteSizeValue blockLoaderSizeOrdinals, + ByteSizeValue blockLoaderSizeScript, + Function> sourcePathResolver ) { this.ctx = ctx; this.fieldExtractPreference = fieldExtractPreference; @@ -44,6 +58,7 @@ class EsqlBlockLoaderContext implements MappedFieldType.BlockLoaderContext { this.warnings = warnings; this.blockLoaderSizeOrdinals = blockLoaderSizeOrdinals; this.blockLoaderSizeScript = blockLoaderSizeScript; + this.sourcePathResolver = sourcePathResolver; } @Override @@ -68,7 +83,7 @@ public SearchLookup lookup() { @Override public Set sourcePaths(String name) { - return ctx.sourcePath(name); + return sourcePathResolver != null ? sourcePathResolver.apply(name) : ctx.sourcePath(name); } @Override From 7d659634544a6df5a12a3a672364356f867df51f Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 18 Mar 2026 13:41:52 +0200 Subject: [PATCH 104/137] Increased test coverage --- .../src/main/resources/unmapped-load.csv-spec | 521 ++++++++++++++++++ .../esql/analysis/AnalyzerUnmappedTests.java | 79 +++ 2 files changed, 600 insertions(+) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index cd68078949cef..ef401e63b076d 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -734,6 +734,527 @@ sample_data | 5033755.0 sample_data | 8268153.0 ; +############################# +# Mapped and non-existent # +############################# + +typeConflictKeywordNonExistentNoCast +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM sample_data, employees METADATA _index +| KEEP _index, message +| SORT _index DESC, message +| LIMIT 12 +; + +_index:keyword | message:keyword +sample_data | Connected to 10.1.0.1 +sample_data | Connected to 10.1.0.2 +sample_data | Connected to 10.1.0.3 +sample_data | Connection error +sample_data | Connection error +sample_data | Connection error +sample_data | Disconnected +employees | null +employees | null +employees | null +employees | null +employees | null +; + +typeConflictKeywordNonExistentCastToKeyword +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM sample_data, employees METADATA _index +| EVAL message = message::keyword +| KEEP _index, message +| SORT _index DESC, message +| LIMIT 12 +; + +_index:keyword | message:keyword +sample_data | Connected to 10.1.0.1 +sample_data | Connected to 10.1.0.2 +sample_data | Connected to 10.1.0.3 +sample_data | Connection error +sample_data | Connection error +sample_data | Connection error +sample_data | Disconnected +employees | null +employees | null +employees | null +employees | null +employees | null +; + +typeConflictLongNonExistentCastToKeyword +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM sample_data, employees METADATA _index +| EVAL event_duration = event_duration::keyword +| KEEP _index, event_duration +| SORT _index DESC, event_duration +| LIMIT 12 +; + +_index:keyword | event_duration:keyword +sample_data | 1232382 +sample_data | 1756467 +sample_data | 2764889 +sample_data | 3450233 +sample_data | 5033755 +sample_data | 725448 +sample_data | 8268153 +employees | null +employees | null +employees | null +employees | null +employees | null +; + +typeConflictLongNonExistentCastToLong +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM sample_data, employees METADATA _index +| EVAL event_duration = event_duration::long +| KEEP _index, event_duration +| SORT _index DESC, event_duration +| LIMIT 12 +; + +_index:keyword | event_duration:long +sample_data | 725448 +sample_data | 1232382 +sample_data | 1756467 +sample_data | 2764889 +sample_data | 3450233 +sample_data | 5033755 +sample_data | 8268153 +employees | null +employees | null +employees | null +employees | null +employees | null +; + +typeConflictLongNonExistentCastToDouble +required_capability: optional_fields_v2 + +SET unmapped_fields="load"\; +FROM sample_data, employees METADATA _index +| EVAL event_duration = event_duration::double +| KEEP _index, event_duration +| SORT _index DESC, event_duration +| LIMIT 12 +; + +_index:keyword | event_duration:double +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +employees | null +employees | null +employees | null +employees | null +employees | null +; + +################################# +# Mapped x 2 and unmapped # +################################# + +typeConflictLongDateUnmappedCastToKeyword +required_capability: optional_fields_v2 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index +| EVAL ts = @timestamp::keyword +| KEEP _index, ts +| SORT _index, ts +; + +_index:keyword | ts:keyword +no_mapping_sample_data | 2024-10-23T12:15:03.360Z +no_mapping_sample_data | 2024-10-23T12:27:28.948Z +no_mapping_sample_data | 2024-10-23T13:33:34.937Z +no_mapping_sample_data | 2024-10-23T13:51:54.732Z +no_mapping_sample_data | 2024-10-23T13:52:55.015Z +no_mapping_sample_data | 2024-10-23T13:53:55.832Z +no_mapping_sample_data | 2024-10-23T13:55:01.543Z +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +sample_data_ts_long | 1698063303360 +sample_data_ts_long | 1698064048948 +sample_data_ts_long | 1698068014937 +sample_data_ts_long | 1698069114732 +sample_data_ts_long | 1698069175015 +sample_data_ts_long | 1698069235832 +sample_data_ts_long | 1698069301543 +; + +typeConflictLongDateUnmappedCastToDouble +required_capability: optional_fields_v2 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index +| EVAL ts = @timestamp::double +| KEEP _index, ts +| SORT _index, ts +; + +warning:Line 3:13: evaluation of [@timestamp::double] failed, treating result as null. Only first 20 failures recorded. +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T12:15:03.360Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T12:27:28.948Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:33:34.937Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:51:54.732Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:52:55.015Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:53:55.832Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:55:01.543Z] +_index:keyword | ts:double +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +sample_data | 1698063303360.0 +sample_data | 1698064048948.0 +sample_data | 1698068014937.0 +sample_data | 1698069114732.0 +sample_data | 1698069175015.0 +sample_data | 1698069235832.0 +sample_data | 1698069301543.0 +sample_data_ts_long | 1698063303360.0 +sample_data_ts_long | 1698064048948.0 +sample_data_ts_long | 1698068014937.0 +sample_data_ts_long | 1698069114732.0 +sample_data_ts_long | 1698069175015.0 +sample_data_ts_long | 1698069235832.0 +sample_data_ts_long | 1698069301543.0 +; + +typeConflictLongDateUnmappedCastToDate +required_capability: optional_fields_v2 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index +| EVAL ts = @timestamp::date +| KEEP _index, ts +| SORT _index, ts +; + +_index:keyword | ts:date +no_mapping_sample_data | 2024-10-23T12:15:03.360Z +no_mapping_sample_data | 2024-10-23T12:27:28.948Z +no_mapping_sample_data | 2024-10-23T13:33:34.937Z +no_mapping_sample_data | 2024-10-23T13:51:54.732Z +no_mapping_sample_data | 2024-10-23T13:52:55.015Z +no_mapping_sample_data | 2024-10-23T13:53:55.832Z +no_mapping_sample_data | 2024-10-23T13:55:01.543Z +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +sample_data_ts_long | 2023-10-23T12:15:03.360Z +sample_data_ts_long | 2023-10-23T12:27:28.948Z +sample_data_ts_long | 2023-10-23T13:33:34.937Z +sample_data_ts_long | 2023-10-23T13:51:54.732Z +sample_data_ts_long | 2023-10-23T13:52:55.015Z +sample_data_ts_long | 2023-10-23T13:53:55.832Z +sample_data_ts_long | 2023-10-23T13:55:01.543Z +; + +############################################# +# Mapped x 2 and non-existent # +############################################# + +typeConflictLongDateNonExistentCastToKeyword +required_capability: optional_fields_v2 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, employees METADATA _index +| EVAL ts = @timestamp::keyword +| KEEP _index, ts +| SORT _index, ts +| LIMIT 25 +; + +_index:keyword | ts:keyword +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +; + +typeConflictLongDateNonExistentCastToDouble +required_capability: optional_fields_v2 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, employees METADATA _index +| EVAL ts = @timestamp::double +| KEEP _index, ts +| SORT _index, ts +| LIMIT 25 +; + +_index:keyword | ts:double +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +; + +typeConflictLongDateNonExistentCastToDate +required_capability: optional_fields_v2 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, employees METADATA _index +| EVAL ts = @timestamp::date +| KEEP _index, ts +| SORT _index, ts +| LIMIT 25 +; + +_index:keyword | ts:datetime +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +; + +##################################################### +# Mapped x 2, unmapped and non-existent (4 indices) # +##################################################### + +typeConflictLongDateUnmappedNonExistentCastToKeyword +required_capability: optional_fields_v2 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data, employees METADATA _index +| EVAL ts = @timestamp::keyword +| KEEP _index, ts +| SORT _index, ts +| LIMIT 30 +; + +_index:keyword | ts:keyword +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +; + +typeConflictLongDateUnmappedNonExistentCastToDouble +required_capability: optional_fields_v2 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data, employees METADATA _index +| EVAL ts = @timestamp::double +| KEEP _index, ts +| SORT _index, ts +| LIMIT 30 +; + +warning:Line 3:13: evaluation of [@timestamp::double] failed, treating result as null. Only first 20 failures recorded. +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T12:15:03.360Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T12:27:28.948Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:33:34.937Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:51:54.732Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:52:55.015Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:53:55.832Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:55:01.543Z] +_index:keyword | ts:double +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +; + +typeConflictLongDateUnmappedNonExistentCastToDate +required_capability: optional_fields_v2 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data, employees METADATA _index +| EVAL ts = @timestamp::date +| KEEP _index, ts +| SORT _index, ts +| LIMIT 30 +; + +_index:keyword | ts:datetime +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +employees | null +; + fieldIsPartiallyUnmappedPartiallySourceIsDisabledMultiIndex required_capability: optional_fields_v2 required_capability: source_field_mapping diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index b47affc484cea..a6ea1df4d33cd 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.esql.analysis; +import org.elasticsearch.action.fieldcaps.FieldCapabilitiesResponse; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.esql.VerificationException; import org.elasticsearch.xpack.esql.action.EsqlCapabilities; @@ -14,15 +15,22 @@ import org.elasticsearch.xpack.esql.core.expression.FoldContext; import org.elasticsearch.xpack.esql.core.expression.MetadataAttribute; import org.elasticsearch.xpack.esql.core.expression.UnresolvedTimestamp; +import org.elasticsearch.xpack.esql.index.IndexResolution; +import org.elasticsearch.xpack.esql.plan.IndexPattern; import org.elasticsearch.xpack.esql.plan.logical.EsRelation; import org.elasticsearch.xpack.esql.plan.logical.Limit; import org.elasticsearch.xpack.esql.plan.logical.Project; import java.util.List; +import java.util.Map; import static org.elasticsearch.xpack.esql.EsqlTestUtils.as; import static org.elasticsearch.xpack.esql.EsqlTestUtils.withDefaultLimitWarning; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyzeStatement; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.fieldCapabilitiesIndexResponse; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.fieldResponseMap; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.indexResolutions; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.mergedResolution; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTests.withInlinestatsWarning; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasSize; @@ -517,11 +525,82 @@ public void testLoadModeDisallowsSubqueryAndFork() { verificationFailure(query, "FORK is not supported with unmapped_fields=\"load\""); } + public void testTypeConflictLongUnmappedNoCast() { + assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); + + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "long")), + fieldCapabilitiesIndexResponse("bar", Map.of()) + ), + List.of() + ); + IndexResolution resolution = mergedResolution("foo,bar", caps); + var indexResolutions = indexResolutions(resolution); + var query = setUnmappedLoad("FROM foo, bar | SORT message"); + verificationFailure(query, indexResolutions, "Cannot use field [message]"); + } + + public void testTypeConflictLongKeywordUnmappedNoCast() { + assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); + + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "long")), + fieldCapabilitiesIndexResponse("bar", fieldResponseMap("message", "keyword")), + fieldCapabilitiesIndexResponse("baz", Map.of()) + ), + List.of() + ); + IndexResolution resolution = mergedResolution("foo,bar,baz", caps); + var indexResolutions = indexResolutions(resolution); + var query = setUnmappedLoad("FROM foo, bar, baz | EVAL x = message + 1"); + verificationFailure(query, indexResolutions, "Cannot use field [message]"); + } + + public void testTypeConflictLongIntUnmappedNoCast() { + assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); + + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "long")), + fieldCapabilitiesIndexResponse("bar", fieldResponseMap("message", "integer")), + fieldCapabilitiesIndexResponse("baz", Map.of()) + ), + List.of() + ); + IndexResolution resolution = mergedResolution("foo,bar,baz", caps); + var indexResolutions = indexResolutions(resolution); + var query = setUnmappedLoad("FROM foo, bar, baz | SORT message"); + verificationFailure(query, indexResolutions, "Cannot use field [message]"); + } + + public void testTypeConflictTextUnmappedNoCast() { + assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); + + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "text")), + fieldCapabilitiesIndexResponse("bar", Map.of()) + ), + List.of() + ); + IndexResolution resolution = mergedResolution("foo,bar", caps); + var indexResolutions = indexResolutions(resolution); + var query = setUnmappedLoad("FROM foo, bar | EVAL x = message"); + verificationFailure(query, indexResolutions, "Cannot use field [message]"); + } + private void verificationFailure(String statement, String expectedFailure) { var e = expectThrows(VerificationException.class, () -> analyzeStatement(statement)); assertThat(e.getMessage(), containsString(expectedFailure)); } + private void verificationFailure(String statement, Map indexResolutions, String expectedFailure) { + var e = expectThrows(VerificationException.class, () -> analyzeStatement(statement, indexResolutions)); + assertThat(e.getMessage(), containsString(expectedFailure)); + } + private static String setUnmappedNullify(String query) { assumeTrue("Requires OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW", EsqlCapabilities.Cap.OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW.isEnabled()); return "SET unmapped_fields=\"nullify\"; " + query; From b58430fd0d67329f03f2c33fed446ba5a330ded7 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Wed, 18 Mar 2026 11:52:59 +0000 Subject: [PATCH 105/137] [CI] Auto commit changes from spotless --- .../src/main/java/org/elasticsearch/xpack/esql/TestAnalyzer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/TestAnalyzer.java b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/TestAnalyzer.java index ab63fd329fba3..89556c26f87d9 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/TestAnalyzer.java +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/TestAnalyzer.java @@ -36,7 +36,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.function.Supplier; import static junit.framework.Assert.assertTrue; From 7ae27881a018901e678a95e9ac3488a1a30e003c Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 18 Mar 2026 15:25:26 +0200 Subject: [PATCH 106/137] Tests --- type_conflict_matrix.md | 36 ++ .../src/main/resources/unmapped-load.csv-spec | 511 +++++++++--------- 2 files changed, 281 insertions(+), 266 deletions(-) create mode 100644 type_conflict_matrix.md diff --git a/type_conflict_matrix.md b/type_conflict_matrix.md new file mode 100644 index 0000000000000..41db9786ad288 --- /dev/null +++ b/type_conflict_matrix.md @@ -0,0 +1,36 @@ +# Mapped and unmapped +[x] 2 indices, a field is mapped in one to a keyword, and in another is unmapped; No casts. (fieldIsPartiallyUnmappedMultiIndex) +[x] 2 indices, a field is mapped in one to a keyword, and in another is unmapped; cast to keyword (typeConflictKeywordUnmappedCastToKeyword) +[x] 2 indices, a field is mapped in one to a long, and in another is unmapped; cast to keyword (typeConflictLongUnmappedCastToKeyword) +[x] 2 indices, a field is mapped in one to a long, and in another is unmapped; cast to long (typeConflictLongUnmappedCastToLong) +[x] 2 indices, a field is mapped in one to a long, and in another is unmapped; cast to double (typeConflictLongUnmappedCastToDouble) + +# mapped and non-existent +[x] 2 indices, a field is mapped in one to a keyword, and in another doesn't exist; No casts. (typeConflictKeywordNonExistentNoCast) +[x] 2 indices, a field is mapped in one to a keyword, and in another doesn't exist; cast to keyword (typeConflictKeywordNonExistentCastToKeyword) +[x] 2 indices, a field is mapped in one to a long, and in another doesn't exist; cast to keyword (typeConflictLongNonExistentCastToKeyword) +[x] 2 indices, a field is mapped in one to a long, and in another doesn't exist; cast to long (typeConflictLongNonExistentCastToLong) +[x] 2 indices, a field is mapped in one to a long, and in another doesn't exist; cast to double (typeConflictLongNonExistentCastToDouble) + +# mapped x 2 and unmapped +[x] 3 indices, field is mapped to long in one, date in another, and unmapped in a third; Cast to keyword (typeConflictLongDateUnmappedCastToKeyword) +[x] 3 indices, field is mapped to long in two, unmapped in a third; Cast to double (typeConflictLongDateUnmappedCastToDouble; uses event_duration to avoid date-string parse warnings) +[x] 3 indices, field is mapped to long in one, date in another, and unmapped in a third; Cast to date (typeConflictLongDateUnmappedCastToDate) + +# mapped x 2 and non-existent +[x] 3 indices, field is mapped to long in one, date in another, and non-existant in a third; Cast to keyword (typeConflictLongDateNonExistentCastToKeyword) +[x] 3 indices, field is mapped to long in one, date in another, and non-existant in a third; Cast to double (typeConflictLongDateNonExistentCastToDouble) +[x] 3 indices, field is mapped to long in one, date in another, and non-existant in a third; Cast to date (typeConflictLongDateNonExistentCastToDate) + +# mapped x 2, unmapped non-existent +[x] 4 indices, field is mapped to long in one, date in another, unmapped in a third, and doesn't exist in a 4th; Cast to keyword (typeConflictLongDateUnmappedNonExistentCastToKeyword) +[x] 4 indices, field is mapped to long in one, date in another, unmapped in a third, and doesn't exist in a 4th; Cast to double (typeConflictLongDateUnmappedNonExistentCastToDouble) +[x] 4 indices, field is mapped to long in one, date in another, unmapped in a third, and doesn't exist in a 4th; Cast to date (typeConflictLongDateUnmappedNonExistentCastToDate) + +# failures (In the AnalyzerUnmappedTests, i.e., non-golden) +[x] 2 indices, a field is mapped in one to long, and in another is unmapped; No casts (testTypeConflictLongUnmappedNoCast) +[x] 3 indices, a field is mapped in one to long, keyword in another, and unmapped in a third; no casts (testTypeConflictLongKeywordUnmappedNoCast) +[x] 3 indices, a field is mapped in one to long, int in another, and unmapped in a third; no casts (testTypeConflictLongIntUnmappedNoCast) +[x] 2 indices, a field is mapped to text in one and unmapped in another; no casts (testTypeConflictTextUnmappedNoCast) + + diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index ef401e63b076d..74c7ec2f99939 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -559,7 +559,7 @@ partiallyUnmappedNonKeywordNoExistence required_capability: optional_fields_v2 SET unmapped_fields="load"\; -FROM sample_data, no_mapping_sample_data, employees METADATA _index +FROM sample_data, no_mapping_sample_data, colors METADATA _index | EVAL event_duration = event_duration::DOUBLE | KEEP _index, event_duration | SORT _index DESC, event_duration @@ -581,10 +581,13 @@ no_mapping_sample_data | 2764888.0 no_mapping_sample_data | 3450232.0 no_mapping_sample_data | 5033754.0 no_mapping_sample_data | 8268152.0 -employees | null -employees | null -employees | null -employees | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null ; partiallyUnmappedMixedTypes @@ -742,10 +745,10 @@ typeConflictKeywordNonExistentNoCast required_capability: optional_fields_v2 SET unmapped_fields="load"\; -FROM sample_data, employees METADATA _index +FROM sample_data, colors METADATA _index | KEEP _index, message | SORT _index DESC, message -| LIMIT 12 +| LIMIT 15 ; _index:keyword | message:keyword @@ -756,22 +759,24 @@ sample_data | Connection error sample_data | Connection error sample_data | Connection error sample_data | Disconnected -employees | null -employees | null -employees | null -employees | null -employees | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null ; typeConflictKeywordNonExistentCastToKeyword required_capability: optional_fields_v2 SET unmapped_fields="load"\; -FROM sample_data, employees METADATA _index +FROM sample_data, colors METADATA _index | EVAL message = message::keyword | KEEP _index, message | SORT _index DESC, message -| LIMIT 12 +| LIMIT 15 ; _index:keyword | message:keyword @@ -782,22 +787,24 @@ sample_data | Connection error sample_data | Connection error sample_data | Connection error sample_data | Disconnected -employees | null -employees | null -employees | null -employees | null -employees | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null ; typeConflictLongNonExistentCastToKeyword required_capability: optional_fields_v2 SET unmapped_fields="load"\; -FROM sample_data, employees METADATA _index +FROM sample_data, colors METADATA _index | EVAL event_duration = event_duration::keyword | KEEP _index, event_duration | SORT _index DESC, event_duration -| LIMIT 12 +| LIMIT 15 ; _index:keyword | event_duration:keyword @@ -808,22 +815,24 @@ sample_data | 3450233 sample_data | 5033755 sample_data | 725448 sample_data | 8268153 -employees | null -employees | null -employees | null -employees | null -employees | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null ; typeConflictLongNonExistentCastToLong required_capability: optional_fields_v2 SET unmapped_fields="load"\; -FROM sample_data, employees METADATA _index +FROM sample_data, colors METADATA _index | EVAL event_duration = event_duration::long | KEEP _index, event_duration | SORT _index DESC, event_duration -| LIMIT 12 +| LIMIT 15 ; _index:keyword | event_duration:long @@ -834,22 +843,24 @@ sample_data | 2764889 sample_data | 3450233 sample_data | 5033755 sample_data | 8268153 -employees | null -employees | null -employees | null -employees | null -employees | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null ; typeConflictLongNonExistentCastToDouble required_capability: optional_fields_v2 SET unmapped_fields="load"\; -FROM sample_data, employees METADATA _index +FROM sample_data, colors METADATA _index | EVAL event_duration = event_duration::double | KEEP _index, event_duration | SORT _index DESC, event_duration -| LIMIT 12 +| LIMIT 15 ; _index:keyword | event_duration:double @@ -860,11 +871,13 @@ sample_data | 2764889.0 sample_data | 3450233.0 sample_data | 5033755.0 sample_data | 8268153.0 -employees | null -employees | null -employees | null -employees | null -employees | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null ; ################################# @@ -912,41 +925,33 @@ required_capability: index_metadata_field SET unmapped_fields="load"\; FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index -| EVAL ts = @timestamp::double -| KEEP _index, ts -| SORT _index, ts +| EVAL d = event_duration::double +| KEEP _index, d +| SORT _index, d ; -warning:Line 3:13: evaluation of [@timestamp::double] failed, treating result as null. Only first 20 failures recorded. -warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T12:15:03.360Z] -warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T12:27:28.948Z] -warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:33:34.937Z] -warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:51:54.732Z] -warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:52:55.015Z] -warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:53:55.832Z] -warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:55:01.543Z] -_index:keyword | ts:double -no_mapping_sample_data | null -no_mapping_sample_data | null -no_mapping_sample_data | null -no_mapping_sample_data | null -no_mapping_sample_data | null -no_mapping_sample_data | null -no_mapping_sample_data | null -sample_data | 1698063303360.0 -sample_data | 1698064048948.0 -sample_data | 1698068014937.0 -sample_data | 1698069114732.0 -sample_data | 1698069175015.0 -sample_data | 1698069235832.0 -sample_data | 1698069301543.0 -sample_data_ts_long | 1698063303360.0 -sample_data_ts_long | 1698064048948.0 -sample_data_ts_long | 1698068014937.0 -sample_data_ts_long | 1698069114732.0 -sample_data_ts_long | 1698069175015.0 -sample_data_ts_long | 1698069235832.0 -sample_data_ts_long | 1698069301543.0 +_index:keyword | d:double +no_mapping_sample_data | 725447.0 +no_mapping_sample_data | 1232381.0 +no_mapping_sample_data | 1756466.0 +no_mapping_sample_data | 2764888.0 +no_mapping_sample_data | 3450232.0 +no_mapping_sample_data | 5033754.0 +no_mapping_sample_data | 8268152.0 +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +sample_data_ts_long | 725447.0 +sample_data_ts_long | 1232381.0 +sample_data_ts_long | 1756466.0 +sample_data_ts_long | 2764888.0 +sample_data_ts_long | 3450232.0 +sample_data_ts_long | 5033754.0 +sample_data_ts_long | 8268152.0 ; typeConflictLongDateUnmappedCastToDate @@ -993,39 +998,35 @@ required_capability: optional_fields_v2 required_capability: index_metadata_field SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, employees METADATA _index +FROM sample_data_ts_long, sample_data, colors METADATA _index | EVAL ts = @timestamp::keyword | KEEP _index, ts -| SORT _index, ts +| SORT _index DESC, ts | LIMIT 25 ; -_index:keyword | ts:keyword -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null +_index:keyword | ts:keyword +sample_data_ts_long | 1698063303360 +sample_data_ts_long | 1698064048948 +sample_data_ts_long | 1698068014937 +sample_data_ts_long | 1698069114732 +sample_data_ts_long | 1698069175015 +sample_data_ts_long | 1698069235832 +sample_data_ts_long | 1698069301543 +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null ; typeConflictLongDateNonExistentCastToDouble @@ -1033,39 +1034,35 @@ required_capability: optional_fields_v2 required_capability: index_metadata_field SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, employees METADATA _index +FROM sample_data_ts_long, sample_data, colors METADATA _index | EVAL ts = @timestamp::double | KEEP _index, ts -| SORT _index, ts +| SORT _index DESC, ts | LIMIT 25 ; -_index:keyword | ts:double -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null +_index:keyword | ts:double +sample_data_ts_long | 1698063303360.0 +sample_data_ts_long | 1698064048948.0 +sample_data_ts_long | 1698068014937.0 +sample_data_ts_long | 1698069114732.0 +sample_data_ts_long | 1698069175015.0 +sample_data_ts_long | 1698069235832.0 +sample_data_ts_long | 1698069301543.0 +sample_data | 1698063303360.0 +sample_data | 1698064048948.0 +sample_data | 1698068014937.0 +sample_data | 1698069114732.0 +sample_data | 1698069175015.0 +sample_data | 1698069235832.0 +sample_data | 1698069301543.0 +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null ; typeConflictLongDateNonExistentCastToDate @@ -1073,39 +1070,35 @@ required_capability: optional_fields_v2 required_capability: index_metadata_field SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, employees METADATA _index +FROM sample_data_ts_long, sample_data, colors METADATA _index | EVAL ts = @timestamp::date | KEEP _index, ts -| SORT _index, ts +| SORT _index DESC, ts | LIMIT 25 ; -_index:keyword | ts:datetime -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null +_index:keyword | ts:datetime +sample_data_ts_long | 2023-10-23T12:15:03.360Z +sample_data_ts_long | 2023-10-23T12:27:28.948Z +sample_data_ts_long | 2023-10-23T13:33:34.937Z +sample_data_ts_long | 2023-10-23T13:51:54.732Z +sample_data_ts_long | 2023-10-23T13:52:55.015Z +sample_data_ts_long | 2023-10-23T13:53:55.832Z +sample_data_ts_long | 2023-10-23T13:55:01.543Z +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null ; ##################################################### @@ -1117,44 +1110,42 @@ required_capability: optional_fields_v2 required_capability: index_metadata_field SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, no_mapping_sample_data, employees METADATA _index +FROM sample_data_ts_long, sample_data, no_mapping_sample_data, colors METADATA _index | EVAL ts = @timestamp::keyword | KEEP _index, ts -| SORT _index, ts +| SORT _index DESC, ts | LIMIT 30 ; -_index:keyword | ts:keyword -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null +_index:keyword | ts:keyword +sample_data_ts_long | 1698063303360 +sample_data_ts_long | 1698064048948 +sample_data_ts_long | 1698068014937 +sample_data_ts_long | 1698069114732 +sample_data_ts_long | 1698069175015 +sample_data_ts_long | 1698069235832 +sample_data_ts_long | 1698069301543 +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +no_mapping_sample_data | 2024-10-23T12:15:03.360Z +no_mapping_sample_data | 2024-10-23T12:27:28.948Z +no_mapping_sample_data | 2024-10-23T13:33:34.937Z +no_mapping_sample_data | 2024-10-23T13:51:54.732Z +no_mapping_sample_data | 2024-10-23T13:52:55.015Z +no_mapping_sample_data | 2024-10-23T13:53:55.832Z +no_mapping_sample_data | 2024-10-23T13:55:01.543Z +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null ; typeConflictLongDateUnmappedNonExistentCastToDouble @@ -1162,52 +1153,42 @@ required_capability: optional_fields_v2 required_capability: index_metadata_field SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, no_mapping_sample_data, employees METADATA _index -| EVAL ts = @timestamp::double -| KEEP _index, ts -| SORT _index, ts +FROM sample_data_ts_long, sample_data, no_mapping_sample_data, colors METADATA _index +| EVAL d = event_duration::double +| KEEP _index, d +| SORT _index DESC, d | LIMIT 30 ; -warning:Line 3:13: evaluation of [@timestamp::double] failed, treating result as null. Only first 20 failures recorded. -warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T12:15:03.360Z] -warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T12:27:28.948Z] -warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:33:34.937Z] -warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:51:54.732Z] -warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:52:55.015Z] -warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:53:55.832Z] -warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:55:01.543Z] -_index:keyword | ts:double -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null +_index:keyword | d:double +sample_data_ts_long | 725447.0 +sample_data_ts_long | 1232381.0 +sample_data_ts_long | 1756466.0 +sample_data_ts_long | 2764888.0 +sample_data_ts_long | 3450232.0 +sample_data_ts_long | 5033754.0 +sample_data_ts_long | 8268152.0 +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +no_mapping_sample_data | 725447.0 +no_mapping_sample_data | 1232381.0 +no_mapping_sample_data | 1756466.0 +no_mapping_sample_data | 2764888.0 +no_mapping_sample_data | 3450232.0 +no_mapping_sample_data | 5033754.0 +no_mapping_sample_data | 8268152.0 +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null ; typeConflictLongDateUnmappedNonExistentCastToDate @@ -1215,44 +1196,42 @@ required_capability: optional_fields_v2 required_capability: index_metadata_field SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, no_mapping_sample_data, employees METADATA _index +FROM sample_data_ts_long, sample_data, no_mapping_sample_data, colors METADATA _index | EVAL ts = @timestamp::date | KEEP _index, ts -| SORT _index, ts +| SORT _index DESC, ts | LIMIT 30 ; -_index:keyword | ts:datetime -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null -employees | null +_index:keyword | ts:datetime +sample_data_ts_long | 2023-10-23T12:15:03.360Z +sample_data_ts_long | 2023-10-23T12:27:28.948Z +sample_data_ts_long | 2023-10-23T13:33:34.937Z +sample_data_ts_long | 2023-10-23T13:51:54.732Z +sample_data_ts_long | 2023-10-23T13:52:55.015Z +sample_data_ts_long | 2023-10-23T13:53:55.832Z +sample_data_ts_long | 2023-10-23T13:55:01.543Z +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +no_mapping_sample_data | 2024-10-23T12:15:03.360Z +no_mapping_sample_data | 2024-10-23T12:27:28.948Z +no_mapping_sample_data | 2024-10-23T13:33:34.937Z +no_mapping_sample_data | 2024-10-23T13:51:54.732Z +no_mapping_sample_data | 2024-10-23T13:52:55.015Z +no_mapping_sample_data | 2024-10-23T13:53:55.832Z +no_mapping_sample_data | 2024-10-23T13:55:01.543Z +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null ; fieldIsPartiallyUnmappedPartiallySourceIsDisabledMultiIndex From 48893bcf5629654546b4c672c41822f7eef5aef2 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 18 Mar 2026 16:08:45 +0200 Subject: [PATCH 107/137] Fix tests --- .../src/main/resources/unmapped-load.csv-spec | 82 ++++++++++++------- 1 file changed, 51 insertions(+), 31 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index 74c7ec2f99939..4c5ffb9b522f3 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -585,9 +585,6 @@ colors | null colors | null colors | null colors | null -colors | null -colors | null -colors | null ; partiallyUnmappedMixedTypes @@ -766,6 +763,7 @@ colors | null colors | null colors | null colors | null +colors | null ; typeConflictKeywordNonExistentCastToKeyword @@ -794,6 +792,7 @@ colors | null colors | null colors | null colors | null +colors | null ; typeConflictLongNonExistentCastToKeyword @@ -822,6 +821,7 @@ colors | null colors | null colors | null colors | null +colors | null ; typeConflictLongNonExistentCastToLong @@ -850,6 +850,7 @@ colors | null colors | null colors | null colors | null +colors | null ; typeConflictLongNonExistentCastToDouble @@ -878,6 +879,7 @@ colors | null colors | null colors | null colors | null +colors | null ; ################################# @@ -945,13 +947,13 @@ sample_data | 2764889.0 sample_data | 3450233.0 sample_data | 5033755.0 sample_data | 8268153.0 -sample_data_ts_long | 725447.0 -sample_data_ts_long | 1232381.0 -sample_data_ts_long | 1756466.0 -sample_data_ts_long | 2764888.0 -sample_data_ts_long | 3450232.0 -sample_data_ts_long | 5033754.0 -sample_data_ts_long | 8268152.0 +sample_data_ts_long | 725448.0 +sample_data_ts_long | 1232382.0 +sample_data_ts_long | 1756467.0 +sample_data_ts_long | 2764889.0 +sample_data_ts_long | 3450233.0 +sample_data_ts_long | 5033755.0 +sample_data_ts_long | 8268153.0 ; typeConflictLongDateUnmappedCastToDate @@ -1027,6 +1029,10 @@ colors | null colors | null colors | null colors | null +colors | null +colors | null +colors | null +colors | null ; typeConflictLongDateNonExistentCastToDouble @@ -1042,20 +1048,24 @@ FROM sample_data_ts_long, sample_data, colors METADATA _index ; _index:keyword | ts:double -sample_data_ts_long | 1698063303360.0 -sample_data_ts_long | 1698064048948.0 -sample_data_ts_long | 1698068014937.0 -sample_data_ts_long | 1698069114732.0 -sample_data_ts_long | 1698069175015.0 -sample_data_ts_long | 1698069235832.0 -sample_data_ts_long | 1698069301543.0 -sample_data | 1698063303360.0 -sample_data | 1698064048948.0 -sample_data | 1698068014937.0 -sample_data | 1698069114732.0 -sample_data | 1698069175015.0 -sample_data | 1698069235832.0 -sample_data | 1698069301543.0 +sample_data_ts_long | 1.69806330336E12 +sample_data_ts_long | 1.698064048948E12 +sample_data_ts_long | 1.698068014937E12 +sample_data_ts_long | 1.698069114732E12 +sample_data_ts_long | 1.698069175015E12 +sample_data_ts_long | 1.698069235832E12 +sample_data_ts_long | 1.698069301543E12 +sample_data | 1.69806330336E12 +sample_data | 1.698064048948E12 +sample_data | 1.698068014937E12 +sample_data | 1.698069114732E12 +sample_data | 1.698069175015E12 +sample_data | 1.698069235832E12 +sample_data | 1.698069301543E12 +colors | null +colors | null +colors | null +colors | null colors | null colors | null colors | null @@ -1099,6 +1109,10 @@ colors | null colors | null colors | null colors | null +colors | null +colors | null +colors | null +colors | null ; ##################################################### @@ -1146,6 +1160,8 @@ colors | null colors | null colors | null colors | null +colors | null +colors | null ; typeConflictLongDateUnmappedNonExistentCastToDouble @@ -1161,13 +1177,13 @@ FROM sample_data_ts_long, sample_data, no_mapping_sample_data, colors METADATA _ ; _index:keyword | d:double -sample_data_ts_long | 725447.0 -sample_data_ts_long | 1232381.0 -sample_data_ts_long | 1756466.0 -sample_data_ts_long | 2764888.0 -sample_data_ts_long | 3450232.0 -sample_data_ts_long | 5033754.0 -sample_data_ts_long | 8268152.0 +sample_data_ts_long | 725448.0 +sample_data_ts_long | 1232382.0 +sample_data_ts_long | 1756467.0 +sample_data_ts_long | 2764889.0 +sample_data_ts_long | 3450233.0 +sample_data_ts_long | 5033755.0 +sample_data_ts_long | 8268153.0 sample_data | 725448.0 sample_data | 1232382.0 sample_data | 1756467.0 @@ -1189,6 +1205,8 @@ colors | null colors | null colors | null colors | null +colors | null +colors | null ; typeConflictLongDateUnmappedNonExistentCastToDate @@ -1232,6 +1250,8 @@ colors | null colors | null colors | null colors | null +colors | null +colors | null ; fieldIsPartiallyUnmappedPartiallySourceIsDisabledMultiIndex From f8071ab3e4d84780f379db903c74bb3c6a3f3db8 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 18 Mar 2026 16:19:33 +0200 Subject: [PATCH 108/137] Refactor verification tests --- .../esql/analysis/AnalyzerUnmappedTests.java | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index 4ca7574fe9053..15ab9c41975c1 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -544,10 +544,11 @@ public void testTypeConflictLongUnmappedNoCast() { ), List.of() ); - IndexResolution resolution = mergedResolution("foo,bar", caps); - var indexResolutions = indexResolutions(resolution); - var query = setUnmappedLoad("FROM foo, bar | SORT message"); - verificationFailure(query, indexResolutions, "Cannot use field [message]"); + verificationFailure( + setUnmappedLoad("FROM foo, bar | SORT message"), + indexResolutions(mergedResolution("foo,bar", caps)), + "Cannot use field [message]" + ); } public void testTypeConflictLongKeywordUnmappedNoCast() { @@ -561,10 +562,11 @@ public void testTypeConflictLongKeywordUnmappedNoCast() { ), List.of() ); - IndexResolution resolution = mergedResolution("foo,bar,baz", caps); - var indexResolutions = indexResolutions(resolution); - var query = setUnmappedLoad("FROM foo, bar, baz | EVAL x = message + 1"); - verificationFailure(query, indexResolutions, "Cannot use field [message]"); + verificationFailure( + setUnmappedLoad("FROM foo, bar, baz | EVAL x = message + 1"), + indexResolutions(mergedResolution("foo,bar,baz", caps)), + "Cannot use field [message]" + ); } public void testTypeConflictLongIntUnmappedNoCast() { @@ -578,10 +580,11 @@ public void testTypeConflictLongIntUnmappedNoCast() { ), List.of() ); - IndexResolution resolution = mergedResolution("foo,bar,baz", caps); - var indexResolutions = indexResolutions(resolution); - var query = setUnmappedLoad("FROM foo, bar, baz | SORT message"); - verificationFailure(query, indexResolutions, "Cannot use field [message]"); + verificationFailure( + setUnmappedLoad("FROM foo, bar, baz | SORT message"), + indexResolutions(mergedResolution("foo,bar,baz", caps)), + "Cannot use field [message]" + ); } public void testTypeConflictTextUnmappedNoCast() { @@ -594,10 +597,11 @@ public void testTypeConflictTextUnmappedNoCast() { ), List.of() ); - IndexResolution resolution = mergedResolution("foo,bar", caps); - var indexResolutions = indexResolutions(resolution); - var query = setUnmappedLoad("FROM foo, bar | EVAL x = message"); - verificationFailure(query, indexResolutions, "Cannot use field [message]"); + verificationFailure( + setUnmappedLoad("FROM foo, bar | EVAL x = message"), + indexResolutions(mergedResolution("foo,bar", caps)), + "Cannot use field [message]" + ); } private void verificationFailure(String statement, String expectedFailure) { From 457a6a7547a742b95a4130212f0c7080840609d0 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 18 Mar 2026 16:20:22 +0200 Subject: [PATCH 109/137] Remove the conflict matrix --- type_conflict_matrix.md | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 type_conflict_matrix.md diff --git a/type_conflict_matrix.md b/type_conflict_matrix.md deleted file mode 100644 index 41db9786ad288..0000000000000 --- a/type_conflict_matrix.md +++ /dev/null @@ -1,36 +0,0 @@ -# Mapped and unmapped -[x] 2 indices, a field is mapped in one to a keyword, and in another is unmapped; No casts. (fieldIsPartiallyUnmappedMultiIndex) -[x] 2 indices, a field is mapped in one to a keyword, and in another is unmapped; cast to keyword (typeConflictKeywordUnmappedCastToKeyword) -[x] 2 indices, a field is mapped in one to a long, and in another is unmapped; cast to keyword (typeConflictLongUnmappedCastToKeyword) -[x] 2 indices, a field is mapped in one to a long, and in another is unmapped; cast to long (typeConflictLongUnmappedCastToLong) -[x] 2 indices, a field is mapped in one to a long, and in another is unmapped; cast to double (typeConflictLongUnmappedCastToDouble) - -# mapped and non-existent -[x] 2 indices, a field is mapped in one to a keyword, and in another doesn't exist; No casts. (typeConflictKeywordNonExistentNoCast) -[x] 2 indices, a field is mapped in one to a keyword, and in another doesn't exist; cast to keyword (typeConflictKeywordNonExistentCastToKeyword) -[x] 2 indices, a field is mapped in one to a long, and in another doesn't exist; cast to keyword (typeConflictLongNonExistentCastToKeyword) -[x] 2 indices, a field is mapped in one to a long, and in another doesn't exist; cast to long (typeConflictLongNonExistentCastToLong) -[x] 2 indices, a field is mapped in one to a long, and in another doesn't exist; cast to double (typeConflictLongNonExistentCastToDouble) - -# mapped x 2 and unmapped -[x] 3 indices, field is mapped to long in one, date in another, and unmapped in a third; Cast to keyword (typeConflictLongDateUnmappedCastToKeyword) -[x] 3 indices, field is mapped to long in two, unmapped in a third; Cast to double (typeConflictLongDateUnmappedCastToDouble; uses event_duration to avoid date-string parse warnings) -[x] 3 indices, field is mapped to long in one, date in another, and unmapped in a third; Cast to date (typeConflictLongDateUnmappedCastToDate) - -# mapped x 2 and non-existent -[x] 3 indices, field is mapped to long in one, date in another, and non-existant in a third; Cast to keyword (typeConflictLongDateNonExistentCastToKeyword) -[x] 3 indices, field is mapped to long in one, date in another, and non-existant in a third; Cast to double (typeConflictLongDateNonExistentCastToDouble) -[x] 3 indices, field is mapped to long in one, date in another, and non-existant in a third; Cast to date (typeConflictLongDateNonExistentCastToDate) - -# mapped x 2, unmapped non-existent -[x] 4 indices, field is mapped to long in one, date in another, unmapped in a third, and doesn't exist in a 4th; Cast to keyword (typeConflictLongDateUnmappedNonExistentCastToKeyword) -[x] 4 indices, field is mapped to long in one, date in another, unmapped in a third, and doesn't exist in a 4th; Cast to double (typeConflictLongDateUnmappedNonExistentCastToDouble) -[x] 4 indices, field is mapped to long in one, date in another, unmapped in a third, and doesn't exist in a 4th; Cast to date (typeConflictLongDateUnmappedNonExistentCastToDate) - -# failures (In the AnalyzerUnmappedTests, i.e., non-golden) -[x] 2 indices, a field is mapped in one to long, and in another is unmapped; No casts (testTypeConflictLongUnmappedNoCast) -[x] 3 indices, a field is mapped in one to long, keyword in another, and unmapped in a third; no casts (testTypeConflictLongKeywordUnmappedNoCast) -[x] 3 indices, a field is mapped in one to long, int in another, and unmapped in a third; no casts (testTypeConflictLongIntUnmappedNoCast) -[x] 2 indices, a field is mapped to text in one and unmapped in another; no casts (testTypeConflictTextUnmappedNoCast) - - From dceaa05a9b8b22ad8567318a77aafae0c55a07bf Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 18 Mar 2026 16:21:45 +0200 Subject: [PATCH 110/137] Fix whitespace --- .../testFixtures/src/main/resources/unmapped-nullify.csv-spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec index 247f89acd3e4a..aa387323c93e4 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec @@ -1035,14 +1035,14 @@ required_capability: sample_v3 SET unmapped_fields="nullify"\; FROM alerts | KEEP kibana.alert.risk_score -| FORK (WHERE true | MV_EXPAND kibana.alert.risk_score) (WHERE true | SAMPLE 0.5) +| FORK (WHERE true | MV_EXPAND kibana.alert.risk_score) (WHERE true | SAMPLE 0.5) | STATS kibana.alert.risk_score = COUNT(*) | EVAL x = LEAST(kibana.alert.risk_score, 52, 60) | KEEP kibana.alert.risk_score ; kibana.alert.risk_score:long -10..20 +10..20 ; From 75a031b53834ddc40bbc4b71e3b0b4ad5dec086c Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 18 Mar 2026 16:51:38 +0200 Subject: [PATCH 111/137] Some refactors --- .../resources/transport/upper_bounds/9.4.csv | 2 +- .../xpack/esql/analysis/Analyzer.java | 20 ++++++++++--------- .../esql/core/type/InvalidMappedField.java | 5 +++-- .../esql/core/type/MultiTypeEsField.java | 4 ++-- .../planner/EsPhysicalOperationProviders.java | 10 ++++------ .../xpack/esql/planner/PlannerUtils.java | 4 ---- .../sql/qa/server/src/main/resources/apps.csv | 2 +- 7 files changed, 22 insertions(+), 25 deletions(-) diff --git a/server/src/main/resources/transport/upper_bounds/9.4.csv b/server/src/main/resources/transport/upper_bounds/9.4.csv index 3f7005d923e60..0aba0184b2e7f 100644 --- a/server/src/main/resources/transport/upper_bounds/9.4.csv +++ b/server/src/main/resources/transport/upper_bounds/9.4.csv @@ -1 +1 @@ -esql_unampped_fields_load,9323000 +esql_unmapped_fields_load,9323000 diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index 6772ddb174196..1fcfb01b86e47 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -15,6 +15,7 @@ import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.Page; import org.elasticsearch.core.Nullable; +import org.elasticsearch.core.Strings; import org.elasticsearch.index.IndexMode; import org.elasticsearch.index.mapper.IdFieldMapper; import org.elasticsearch.logging.Logger; @@ -1222,17 +1223,18 @@ private static FieldAttribute invalidInsistAttribute(FieldAttribute fa, List r.isPartiallyUnmappedField(name)) .findFirst() - .orElseThrow(); - Map> typesToIndices = new TreeMap<>(); + .orElseThrow(() -> new IllegalStateException(Strings.format("No index with unmapped '%s' found", name))); + InvalidMappedField field = InvalidMappedField.potentiallyUnmapped(name, getTypesToIndices(fa, esIndex)); + return new FieldAttribute(fa.source(), null, fa.qualifier(), name, field); + } + + private static Map> getTypesToIndices(FieldAttribute fa, EsIndex esIndex) { if (fa.field() instanceof InvalidMappedField imf) { - typesToIndices.putAll(imf.getTypesToIndices()); - } else { - TreeSet indicesWithField = new TreeSet<>(esIndex.concreteQualifiedIndices()); - indicesWithField.removeAll(esIndex.getUnmappedIndices(fa.name())); - typesToIndices.put(fa.dataType().typeName(), indicesWithField); + return imf.getTypesToIndices(); } - EsField field = InvalidMappedField.potentiallyUnmapped(name, typesToIndices); - return new FieldAttribute(fa.source(), null, fa.qualifier(), name, field); + TreeSet indicesWithField = new TreeSet<>(esIndex.concreteQualifiedIndices()); + indicesWithField.removeAll(esIndex.getUnmappedIndices(fa.name())); + return new TreeMap<>(Map.of(fa.name(), indicesWithField)); } public static FieldAttribute insistKeyword(Attribute attribute) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/InvalidMappedField.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/InvalidMappedField.java index eaf64fd686bb4..ee9db91834108 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/InvalidMappedField.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/InvalidMappedField.java @@ -33,7 +33,6 @@ public class InvalidMappedField extends EsField { private final String errorMessage; private final Map> typesToIndices; - // Marks the field as being unmapped in some indices. private final boolean isPotentiallyUnmapped; public InvalidMappedField(String name, String errorMessage, Map properties) { @@ -49,7 +48,9 @@ public InvalidMappedField(String name, Map> typesToIndices) } /** - * Constructor supporting union types, used in ES|QL. + * A {@link InvalidMappedField} is potentially unmapped if at least one index does not contain a mapping for the field, and the user + * requested we load the values from {@code _source}. In that case, there is an additional type conflict since we treat unmapped fields + * as {@link DataType#KEYWORD}. */ public static InvalidMappedField potentiallyUnmapped(String name, Map> typesToIndices) { return new InvalidMappedField( diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java index fbed7fa3e8a43..242859d38f961 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java @@ -32,13 +32,13 @@ * type conversion is done at the data node level. */ public class MultiTypeEsField extends EsField { - private static final TransportVersion UNMAPPED_FIELDS_LOAD = TransportVersion.fromName("esql_unampped_fields_load"); + private static final TransportVersion UNMAPPED_FIELDS_LOAD = TransportVersion.fromName("esql_unmapped_fields_load"); private final Map indexToConversionExpressions; /** * If this is not {@code null}, then this expression should be used to convert the field value in case the field is not mapped in an - * index, to convert the {@link DataType#KEYWORD} to the target type. + * index from {@link DataType#KEYWORD} to the target type. */ @Nullable private final Expression potentiallyUnmappedExpression; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java index d05be2cefbef8..ff6301e401124 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java @@ -261,14 +261,12 @@ private ValuesSourceReaderOperator.LoaderAndConverter blockLoaderAndConverter( Expression conversion = unionTypes.getConversionExpressionForIndex(indexName); if (conversion == null) { Expression potentiallyUnmapped = unionTypes.getPotentiallyUnmappedExpression(); - if (potentiallyUnmapped != null && potentiallyUnmapped instanceof AbstractConvertFunction convert) { - String unmappedFieldName = ((FieldAttribute) convert.field()).fieldName().string(); - shardContext = wrapWithUnmappedFieldContext(shardContext, new PotentiallyUnmappedKeywordEsField(unmappedFieldName)); - conversion = potentiallyUnmapped; - fieldName = unmappedFieldName; - } else { + if (!(potentiallyUnmapped instanceof AbstractConvertFunction convert)) { return ValuesSourceReaderOperator.LOAD_CONSTANT_NULLS; } + fieldName = ((FieldAttribute) convert.field()).fieldName().string(); + shardContext = wrapWithUnmappedFieldContext(shardContext, new PotentiallyUnmappedKeywordEsField(fieldName)); + conversion = potentiallyUnmapped; } if (conversion instanceof BlockLoaderExpression ble) { BlockLoaderExpression.PushedBlockLoaderExpression e = ble.tryPushToFieldLoading(SearchStats.EMPTY); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java index c26df6313564c..86324ed15d0a5 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java @@ -79,8 +79,6 @@ import java.util.stream.Collectors; import static org.elasticsearch.index.mapper.MappedFieldType.FieldExtractPreference.DOC_VALUES; -import static org.elasticsearch.index.mapper.MappedFieldType.FieldExtractPreference.EXTRACT_SPATIAL_BOUNDS; -import static org.elasticsearch.index.mapper.MappedFieldType.FieldExtractPreference.EXTRACT_SPATIAL_CENTROID; import static org.elasticsearch.index.mapper.MappedFieldType.FieldExtractPreference.NONE; import static org.elasticsearch.index.query.QueryBuilders.boolQuery; import static org.elasticsearch.xpack.esql.capabilities.TranslationAware.translatable; @@ -377,8 +375,6 @@ public static PhysicalPlan localPlan( return EstimatesRowSize.estimateRowSize(f.estimatedRowSize(), localOptimized); }); - // TODO add a test assertion for the consistency checker (see - // https://github.com/elastic/elasticsearch/pull/141082/changes#r2745334028); PhysicalPlan resultPlan = isCoordPlan.get() ? plan : localPhysicalPlan; return resultPlan; } diff --git a/x-pack/plugin/sql/qa/server/src/main/resources/apps.csv b/x-pack/plugin/sql/qa/server/src/main/resources/apps.csv index 7fefd7bfb316f..9bd4123424f02 100644 --- a/x-pack/plugin/sql/qa/server/src/main/resources/apps.csv +++ b/x-pack/plugin/sql/qa/server/src/main/resources/apps.csv @@ -1,4 +1,4 @@ -id,version2,name +id,version,name 1,1,aaaaa 2,2.1,bbbbb 3,2.3.4,ccccc From 3638353b0409f214c1255aadf6badf7a455c5d49 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 19 Mar 2026 01:05:22 +0200 Subject: [PATCH 112/137] Bug fixes --- ...l_unampped_fields_load.csv => esql_unmapped_fields_load.csv} | 0 .../java/org/elasticsearch/xpack/esql/analysis/Analyzer.java | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename server/src/main/resources/transport/definitions/referable/{esql_unampped_fields_load.csv => esql_unmapped_fields_load.csv} (100%) diff --git a/server/src/main/resources/transport/definitions/referable/esql_unampped_fields_load.csv b/server/src/main/resources/transport/definitions/referable/esql_unmapped_fields_load.csv similarity index 100% rename from server/src/main/resources/transport/definitions/referable/esql_unampped_fields_load.csv rename to server/src/main/resources/transport/definitions/referable/esql_unmapped_fields_load.csv diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index 1fcfb01b86e47..a65155e46b2c1 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -1234,7 +1234,7 @@ private static Map> getTypesToIndices(FieldAttribute fa, EsI } TreeSet indicesWithField = new TreeSet<>(esIndex.concreteQualifiedIndices()); indicesWithField.removeAll(esIndex.getUnmappedIndices(fa.name())); - return new TreeMap<>(Map.of(fa.name(), indicesWithField)); + return new TreeMap<>(Map.of(fa.dataType().typeName(), indicesWithField)); } public static FieldAttribute insistKeyword(Attribute attribute) { From 4e9e50e0a4e01388020a6c87e8cc24142e11bf80 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 19 Mar 2026 15:22:51 +0200 Subject: [PATCH 113/137] Add failing test with MAX_CONCURRENT_SHARDS_PER_NODE --- .../xpack/esql/action/EsqlActionIT.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlActionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlActionIT.java index 80ca59085f9b7..c6ce22b8f16a5 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlActionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlActionIT.java @@ -2653,4 +2653,50 @@ public void testExplainWithApproximation() { } } } + + /** + * Verifies that unmapped fields are loaded from _source (not replaced with constant nulls) when shards are processed one at a time. + * Reproducer for a bug where single-shard concurrency causes potentiallyUnmappedExpression to be lost during shard-level planning, + * resulting in null values instead of the actual _source values for unmapped fields. + */ + public void testUnmappedFieldsLoadWithSingleShardConcurrency() { + assumeTrue("requires unmapped fields load support", EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled()); + assertAcked(prepareCreate("test_mapped").setMapping("event_duration", "type=long")); + assertAcked(prepareCreate("test_unmapped").setMapping(""" + {"dynamic": false, "properties": {}}""")); + + client().prepareBulk() + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .add(prepareIndex("test_mapped").setSource(Map.of("event_duration", 100))) + .add(prepareIndex("test_mapped").setSource(Map.of("event_duration", 200))) + .add(prepareIndex("test_unmapped").setSource(Map.of("event_duration", 10))) + .add(prepareIndex("test_unmapped").setSource(Map.of("event_duration", 20))) + .get(); + + var pragmas = new QueryPragmas(Settings.builder().put(QueryPragmas.MAX_CONCURRENT_SHARDS_PER_NODE.getKey(), 1).build()); + try (var resp = run(syncEsqlQueryRequest(""" + SET unmapped_fields="load"; + FROM test_mapped, test_unmapped METADATA _index + | EVAL event_duration = event_duration::long + | KEEP _index, event_duration + | SORT _index, event_duration""").pragmas(pragmas))) { + + assertThat( + resp.columns(), + equalTo(List.of(new ColumnInfoImpl("_index", "keyword", null), new ColumnInfoImpl("event_duration", "long", null))) + ); + + assertThat( + getValuesList(resp), + equalTo( + List.of( + List.of("test_mapped", 100L), + List.of("test_mapped", 200L), + List.of("test_unmapped", 10L), + List.of("test_unmapped", 20L) + ) + ) + ); + } + } } From a3a1dc7d08e312ee49ea08c547c95576e0ef2937 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 19 Mar 2026 19:00:58 +0200 Subject: [PATCH 114/137] Fix MultiTypeEsFeild bug --- .../rules/logical/local/ReplaceFieldWithConstantOrNull.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java index 465c429371a25..291e530d447e6 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java @@ -16,6 +16,7 @@ import org.elasticsearch.xpack.esql.core.expression.Literal; import org.elasticsearch.xpack.esql.core.expression.MetadataAttribute; import org.elasticsearch.xpack.esql.core.expression.TimeSeriesMetadataAttribute; +import org.elasticsearch.xpack.esql.core.type.MultiTypeEsField; import org.elasticsearch.xpack.esql.core.type.PotentiallyUnmappedKeywordEsField; import org.elasticsearch.xpack.esql.optimizer.LocalLogicalOptimizerContext; import org.elasticsearch.xpack.esql.optimizer.rules.RuleUtils; @@ -87,6 +88,7 @@ else if (esRelation.indexMode() == IndexMode.STANDARD) { // Also retain fields from lookup indices and external sources because we do not have stats for these. Predicate shouldBeRetained = f -> f instanceof TimeSeriesMetadataAttribute || f.field() instanceof PotentiallyUnmappedKeywordEsField + || (f.field() instanceof MultiTypeEsField mtf && mtf.getPotentiallyUnmappedExpression() != null) // The source (or doc) field is added to the relation output as a hack to enable late materialization in the reduce driver. || EsQueryExec.isDocAttribute(f) || localLogicalOptimizerContext.searchStats().exists(f.fieldName()) From 494a56f97025115703aa7d3990d99e98261f2867 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Fri, 20 Mar 2026 12:51:22 +0200 Subject: [PATCH 115/137] Undo alignment fixes to nullify --- .../main/resources/unmapped-nullify.csv-spec | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec index aa387323c93e4..00550ca0a1eb1 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-nullify.csv-spec @@ -381,8 +381,8 @@ FROM languages | STATS c = COUNT(*) BY does_not_exist ; -c:long | does_not_exist:null -4 | null +c:long |does_not_exist:null +4 |null ; statsGroupAliasShadowingSourceColumnNoFilter @@ -393,8 +393,8 @@ FROM languages | STATS c = COUNT(*) BY language_code = does_not_exist ; -c:long | language_code:null -4 | null +c:long |language_code:null +4 |null ; statsGroupAliasShadowingSourceColumnWithFilter @@ -406,8 +406,8 @@ FROM languages | STATS c = COUNT(*) BY language_code = does_not_exist, language_name ; -c:long | language_code:null | language_name :keyword -1 | null | English +c:long |language_code:null |language_name :keyword +1 |null |English ; statsGroupAliasShadowingSourceColumnWithFilterAndAggExpression @@ -420,8 +420,8 @@ FROM languages BY language_code = does_not_exist1::INTEGER + does_not_exist2::INTEGER + language_code, language_name ; -c:long | language_code:integer | language_name :keyword -1 | null | English +c:long |language_code:integer |language_name :keyword +1 |null |English ; inlinestatsSum @@ -550,11 +550,11 @@ FROM sample_data, sample_data_str, | SORT client_ip ; -client_ip:ip | foo:null | bar:keyword | baz:null -172.21.0.5 | null | null | null -172.21.2.113 | null | null | null -172.21.2.162 | null | null | null -172.21.3.15 | null | null | null +client_ip:ip |foo:null |bar:keyword |baz:null +172.21.0.5 |null |null |null +172.21.2.113 |null |null |null +172.21.2.162 |null |null |null +172.21.3.15 |null |null |null ; forkBranchesWithDifferentSchemas @@ -1005,7 +1005,7 @@ FROM employees | EVAL y = coalesce(bar, baz) ; -avg_worked_seconds:long | birth_date:date | emp_no:integer | first_name:keyword | gender:keyword | height:double | height.float:double | height.half_float:double | height.scaled_float:double | hire_date:date | is_rehired:boolean | job_positions:keyword | languages:integer | languages.byte:integer | languages.long:long | languages.short:integer | last_name:keyword | salary:integer | salary_change:double | salary_change.int:integer | salary_change.keyword:keyword | salary_change.long:long | still_hired:boolean | foo:null | bar:null | baz:null | y:null +avg_worked_seconds:long | birth_date:date | emp_no:integer | first_name:keyword | gender:keyword | height:double | height.float:double | height.half_float:double | height.scaled_float:double | hire_date:date | is_rehired:boolean | job_positions:keyword | languages:integer | languages.byte:integer | languages.long:long | languages.short:integer | last_name:keyword | salary:integer | salary_change:double | salary_change.int:integer | salary_change.keyword:keyword | salary_change.long:long | still_hired:boolean | foo:null | bar:null | baz:null | y:null ; @@ -1035,14 +1035,14 @@ required_capability: sample_v3 SET unmapped_fields="nullify"\; FROM alerts | KEEP kibana.alert.risk_score -| FORK (WHERE true | MV_EXPAND kibana.alert.risk_score) (WHERE true | SAMPLE 0.5) +| FORK (WHERE true | MV_EXPAND kibana.alert.risk_score) (WHERE true | SAMPLE 0.5) | STATS kibana.alert.risk_score = COUNT(*) | EVAL x = LEAST(kibana.alert.risk_score, 52, 60) | KEEP kibana.alert.risk_score ; kibana.alert.risk_score:long -10..20 +10..20 ; @@ -1057,6 +1057,6 @@ ROW a = 12::long | DROP a ; -_fork:keyword | x:long -fork1 | 12 +_fork:keyword | x:long +fork1 | 12 ; From 1062f858212ce2d104dad0984b0d6f4c4e08ff90 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Fri, 20 Mar 2026 13:14:00 +0200 Subject: [PATCH 116/137] More robust handling of esindex --- .../xpack/esql/analysis/Analyzer.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index a65155e46b2c1..b93d91c0f87da 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -1219,11 +1219,23 @@ private Attribute resolveInsistAttribute(Attribute attribute, List ch private static FieldAttribute invalidInsistAttribute(FieldAttribute fa, List indexResolutions) { String name = fa.name(); - EsIndex esIndex = indexResolutions.stream() + List unmappedIndices = indexResolutions.stream() .map(IndexResolution::get) .filter(r -> r.isPartiallyUnmappedField(name)) - .findFirst() - .orElseThrow(() -> new IllegalStateException(Strings.format("No index with unmapped '%s' found", name))); + .toList(); + if (unmappedIndices.isEmpty()) { + throw new IllegalStateException(Strings.format("No index with unmapped '%s' found", name)); + } + if (unmappedIndices.size() > 1) { + throw new IllegalStateException( + Strings.format( + "Multiple indices with unmapped '%s' found: %s; Unexpected since we forks/subqueries/etc. are currently disabled!", + name, + unmappedIndices.stream().map(EsIndex::name).toList() + ) + ); + } + EsIndex esIndex = unmappedIndices.getFirst(); InvalidMappedField field = InvalidMappedField.potentiallyUnmapped(name, getTypesToIndices(fa, esIndex)); return new FieldAttribute(fa.source(), null, fa.qualifier(), name, field); } From 6f4fb47328c4e541805561192e0ef68f137b2ee5 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Fri, 20 Mar 2026 14:49:17 +0200 Subject: [PATCH 117/137] After self (?) review --- .../_nightly/esql/QueryPlanningBenchmark.java | 3 +- .../esql/ViewResolutionBenchmarkBase.java | 2 +- .../xpack/esql/analysis/Analyzer.java | 1 + .../esql/core/type/InvalidMappedField.java | 7 ++- .../xpack/esql/datasources/README.md | 7 +++ .../fulltext/SingleFieldFullTextFunction.java | 1 - .../planner/EsPhysicalOperationProviders.java | 10 ++--- .../esql/planner/EsqlBlockLoaderContext.java | 17 +------ .../xpack/esql/analysis/AnalyzerTests.java | 44 +------------------ 9 files changed, 20 insertions(+), 72 deletions(-) diff --git a/benchmarks/src/main/java/org/elasticsearch/benchmark/_nightly/esql/QueryPlanningBenchmark.java b/benchmarks/src/main/java/org/elasticsearch/benchmark/_nightly/esql/QueryPlanningBenchmark.java index aeee2cef4c78d..e7664a03074dc 100644 --- a/benchmarks/src/main/java/org/elasticsearch/benchmark/_nightly/esql/QueryPlanningBenchmark.java +++ b/benchmarks/src/main/java/org/elasticsearch/benchmark/_nightly/esql/QueryPlanningBenchmark.java @@ -55,7 +55,6 @@ import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; -import java.util.Set; import java.util.concurrent.TimeUnit; import static java.util.Collections.emptyMap; @@ -110,7 +109,7 @@ public void setup() { mapping.put("field" + i, new EsField("field-" + i, TEXT, emptyMap(), true, EsField.TimeSeriesFieldType.NONE)); } - var esIndex = new EsIndex("test", mapping, Map.of("test", IndexMode.STANDARD), Map.of(), Map.of(), Set.of()); + var esIndex = new EsIndex("test", mapping, Map.of("test", IndexMode.STANDARD), Map.of(), Map.of(), Map.of()); var functionRegistry = new EsqlFunctionRegistry(); parser = new EsqlParser(new EsqlConfig(functionRegistry)); diff --git a/benchmarks/src/main/java/org/elasticsearch/benchmark/esql/ViewResolutionBenchmarkBase.java b/benchmarks/src/main/java/org/elasticsearch/benchmark/esql/ViewResolutionBenchmarkBase.java index 376e371fbe4a0..6ee4e9ba5a58a 100644 --- a/benchmarks/src/main/java/org/elasticsearch/benchmark/esql/ViewResolutionBenchmarkBase.java +++ b/benchmarks/src/main/java/org/elasticsearch/benchmark/esql/ViewResolutionBenchmarkBase.java @@ -171,7 +171,7 @@ public void setup() { String name = "col" + i; mapping.put(name, new EsField(name, KEYWORD, emptyMap(), true, EsField.TimeSeriesFieldType.NONE)); } - EsIndex esIndex = new EsIndex("test", mapping, Map.of("test", IndexMode.STANDARD), Map.of(), Map.of(), Set.of()); + EsIndex esIndex = new EsIndex("test", mapping, Map.of("test", IndexMode.STANDARD), Map.of(), Map.of(), Map.of()); Configuration config = new Configuration( DateUtils.UTC, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index b93d91c0f87da..5be18de76ead9 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -1244,6 +1244,7 @@ private static Map> getTypesToIndices(FieldAttribute fa, EsI if (fa.field() instanceof InvalidMappedField imf) { return imf.getTypesToIndices(); } + // Field isn't currently invalid, meaning it's mapped to a single type in all the indices where it's actually mapped. TreeSet indicesWithField = new TreeSet<>(esIndex.concreteQualifiedIndices()); indicesWithField.removeAll(esIndex.getUnmappedIndices(fa.name())); return new TreeMap<>(Map.of(fa.dataType().typeName(), indicesWithField)); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/InvalidMappedField.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/InvalidMappedField.java index ee9db91834108..45f3a9c59b3d8 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/InvalidMappedField.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/InvalidMappedField.java @@ -48,9 +48,9 @@ public InvalidMappedField(String name, Map> typesToIndices) } /** - * A {@link InvalidMappedField} is potentially unmapped if at least one index does not contain a mapping for the field, and the user - * requested we load the values from {@code _source}. In that case, there is an additional type conflict since we treat unmapped fields - * as {@link DataType#KEYWORD}. + * An {@link InvalidMappedField} is potentially unmapped if at least one index does not contain a mapping for the field, and the user + * requested we load the values from {@code _source}. In that case, there is (possibly) an additional type conflict since we treat + * unmapped fields as {@link DataType#KEYWORD}. */ public static InvalidMappedField potentiallyUnmapped(String name, Map> typesToIndices) { return new InvalidMappedField( @@ -149,7 +149,6 @@ private static String makeErrorMessage(Map> typesToIndices, errorMessage.append(typesToIndices.size() + (isInsistKeywordOnlyKeyword ? 1 : 0)); errorMessage.append("] incompatible types: "); boolean first = true; - // FIXME(gal, NOCOMMIT) Rephrase to use LOAD if (isInsistKeywordOnlyKeyword) { first = false; errorMessage.append("[keyword] enforced by INSIST command"); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/datasources/README.md b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/datasources/README.md index ae0d75166a29e..149bd81e5eb52 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/datasources/README.md +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/datasources/README.md @@ -336,11 +336,14 @@ x-pack/plugin/ │ ├── GcsDataSourcePlugin.java │ └── GcsStorageProvider.java │ +<<<<<<< HEAD ├── esql-datasource-azure/ # Azure Blob Storage plugin │ └── src/main/java/.../azure/ │ ├── AzureDataSourcePlugin.java │ └── AzureStorageProvider.java │ +======= +>>>>>>> upstream/main └── esql-datasource-iceberg/ # Iceberg table catalog plugin ├── build.gradle # Iceberg, Arrow, AWS SDK dependencies └── src/main/java/.../iceberg/ @@ -378,7 +381,11 @@ Run tests: ## Future Enhancements +<<<<<<< HEAD +1. **Additional Storage Providers** - HDFS +======= 1. **Additional Storage Providers** - HDFS, Azure Blob +>>>>>>> upstream/main 2. **Additional Format Readers** - ORC, Avro, JSON Lines 3. **Additional Table Catalogs** - Delta Lake, Apache Hudi 4. **Performance Optimizations** - File splitting, parallel reads, caching diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/SingleFieldFullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/SingleFieldFullTextFunction.java index 3f8f1818af594..fd0899585ac37 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/SingleFieldFullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/SingleFieldFullTextFunction.java @@ -240,7 +240,6 @@ protected String expectedQueryTypesString() { } static String expectedTypesAsString(Set dataTypes) { - // FIXME(gal, NOCOMMIT) Extract this to a separate PR. return String.join(", ", dataTypes.stream().map(dt -> dt.name().toLowerCase(Locale.ROOT)).sorted().toList()); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java index ff6301e401124..0b4b5aacffe37 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java @@ -75,6 +75,7 @@ import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; import org.elasticsearch.xpack.esql.core.expression.FoldContext; +import org.elasticsearch.xpack.esql.core.expression.NamedExpression; import org.elasticsearch.xpack.esql.core.expression.TimeSeriesMetadataAttribute; import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.core.type.FunctionEsField; @@ -215,8 +216,8 @@ public final PhysicalOperation fieldExtractPhysicalOperation( ); } - private static String getFieldName(Attribute attr) { - // Do not use the field attribute name, this can deviate from the field name for union types. + private static String getFieldName(NamedExpression attr) { + // Do not use the field attribute name, as it can deviate from the field name for union types. return attr instanceof FieldAttribute fa ? fa.fieldName().string() : attr.name(); } @@ -264,7 +265,7 @@ private ValuesSourceReaderOperator.LoaderAndConverter blockLoaderAndConverter( if (!(potentiallyUnmapped instanceof AbstractConvertFunction convert)) { return ValuesSourceReaderOperator.LOAD_CONSTANT_NULLS; } - fieldName = ((FieldAttribute) convert.field()).fieldName().string(); + fieldName = getFieldName((NamedExpression) convert.field()); shardContext = wrapWithUnmappedFieldContext(shardContext, new PotentiallyUnmappedKeywordEsField(fieldName)); conversion = potentiallyUnmapped; } @@ -637,8 +638,7 @@ public BlockLoader blockLoader( blockLoaderFunctionConfig, warnings, blockLoaderSizeOrdinals, - blockLoaderSizeScript, - this::resolveSourcePaths + blockLoaderSizeScript ) ); if (loader == null) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsqlBlockLoaderContext.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsqlBlockLoaderContext.java index b215237cb51a8..f7788e0acd05d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsqlBlockLoaderContext.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsqlBlockLoaderContext.java @@ -18,7 +18,6 @@ import org.elasticsearch.search.lookup.SearchLookup; import java.util.Set; -import java.util.function.Function; /** * {@link MappedFieldType.BlockLoaderContext} implementation for ESQL. @@ -30,7 +29,6 @@ class EsqlBlockLoaderContext implements MappedFieldType.BlockLoaderContext { private final Warnings warnings; private final ByteSizeValue blockLoaderSizeOrdinals; private final ByteSizeValue blockLoaderSizeScript; - private final Function> sourcePathResolver; EsqlBlockLoaderContext( SearchExecutionContext ctx, @@ -39,18 +37,6 @@ class EsqlBlockLoaderContext implements MappedFieldType.BlockLoaderContext { Warnings warnings, ByteSizeValue blockLoaderSizeOrdinals, ByteSizeValue blockLoaderSizeScript - ) { - this(ctx, fieldExtractPreference, blockLoaderFunctionConfig, warnings, blockLoaderSizeOrdinals, blockLoaderSizeScript, null); - } - - EsqlBlockLoaderContext( - SearchExecutionContext ctx, - MappedFieldType.FieldExtractPreference fieldExtractPreference, - BlockLoaderFunctionConfig blockLoaderFunctionConfig, - Warnings warnings, - ByteSizeValue blockLoaderSizeOrdinals, - ByteSizeValue blockLoaderSizeScript, - Function> sourcePathResolver ) { this.ctx = ctx; this.fieldExtractPreference = fieldExtractPreference; @@ -58,7 +44,6 @@ class EsqlBlockLoaderContext implements MappedFieldType.BlockLoaderContext { this.warnings = warnings; this.blockLoaderSizeOrdinals = blockLoaderSizeOrdinals; this.blockLoaderSizeScript = blockLoaderSizeScript; - this.sourcePathResolver = sourcePathResolver; } @Override @@ -83,7 +68,7 @@ public SearchLookup lookup() { @Override public Set sourcePaths(String name) { - return sourcePathResolver != null ? sourcePathResolver.apply(name) : ctx.sourcePath(name); + return ctx.sourcePath(name); } @Override 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 6afc977f7f769..4e17d6b685ebc 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 @@ -3491,7 +3491,7 @@ public void testResolveInsist_multiIndexFieldExistsWithSingleTypeButIsNotKeyword assertThat(attribute.name(), is("message")); String expected = "Cannot use field [message] due to ambiguities being mapped as [2] incompatible types: " - + "[keyword] enforced by INSIST command, and [long] in index mappings"; + + "[keyword] enforced by INSIST command, [long] in [foo]"; assertThat(attribute.unresolvedMessage(), is(expected)); } @@ -3517,25 +3517,6 @@ public void testResolveInsist_multiIndexFieldPartiallyExistsWithMultiTypesNoKeyw assertThat(attr.unresolvedMessage(), is(expected)); } - public void testResolveInsist_multiIndexSameMapping_fieldIsMapped() { - assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); - - FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( - List.of( - fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "long")), - fieldCapabilitiesIndexResponse("bar", fieldResponseMap("message", "long")) - ), - List.of() - ); - IndexResolution resolution = mergedResolution("foo,bar", caps); - var plan = analyze("FROM foo, bar | INSIST_🐔 message", analyzer(resolution, TEST_VERIFIER)); - var limit = as(plan, Limit.class); - var insist = as(limit.child(), Insist.class); - var attribute = (FieldAttribute) EsqlTestUtils.singleValue(insist.output()); - assertThat(attribute.name(), is("message")); - assertThat(attribute.dataType(), is(DataType.LONG)); - } - public void testResolveInsist_multiIndexFieldPartiallyExistsWithMultiTypesWithKeyword_createsAnInvalidMappedField() { assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); @@ -3559,29 +3540,6 @@ public void testResolveInsist_multiIndexFieldPartiallyExistsWithMultiTypesWithKe assertThat(attr.unresolvedMessage(), is(expected)); } - public void testResolveInsist_multiIndexFieldPartiallyExistsWithMultiTypesWithCast_castsAreNotSupported() { - assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); - - FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( - List.of( - fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "long")), - fieldCapabilitiesIndexResponse("bar", fieldResponseMap("message", "date")), - fieldCapabilitiesIndexResponse("bazz", Map.of()) - ), - List.of() - ); - IndexResolution resolution = mergedResolution("foo,bar", caps); - VerificationException e = expectThrows( - VerificationException.class, - () -> analyze("FROM foo, bar | INSIST_🐔 message | EVAL message = message :: keyword", analyzer(resolution, TEST_VERIFIER)) - ); - // This isn't the most informative error, but it'll do for now. - assertThat( - e.getMessage(), - containsString("EVAL does not support type [unsupported] as the return data type of expression [message]") - ); - } - public void testResolveDenseVector() { FieldCapabilitiesResponse caps = FieldCapabilitiesResponse.builder() .withIndexResponses( From a0a0d06a9382867a8615ed0fe016d69555167e1f Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 23 Mar 2026 18:45:17 +0200 Subject: [PATCH 118/137] SOME fixes, so cursor can work on it in another PC --- .../generative/GenerativeForkRestTest.java | 4 +- .../src/main/resources/flattened.csv-spec | 30 +- .../src/main/resources/unmapped-load.csv-spec | 823 +----------------- .../unmapped-type-conflicts.csv-spec | 803 +++++++++++++++++ .../xpack/esql/action/EsqlActionIT.java | 2 +- .../xpack/esql/action/EsqlCapabilities.java | 5 +- .../xpack/esql/analysis/Analyzer.java | 48 +- .../xpack/esql/plan/QuerySettings.java | 4 +- .../planner/EsPhysicalOperationProviders.java | 10 - .../esql/analysis/AnalyzerTestUtils.java | 2 +- .../esql/analysis/AnalyzerUnmappedTests.java | 2 +- .../optimizer/UnmappedGoldenTestCase.java | 2 +- .../xpack/esql/parser/SetParserTests.java | 4 +- .../xpack/esql/plan/QuerySettingsTests.java | 2 +- .../esql/type/InvalidMappedFieldTests.java | 1 + 15 files changed, 901 insertions(+), 841 deletions(-) create mode 100644 x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec diff --git a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/generative/GenerativeForkRestTest.java b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/generative/GenerativeForkRestTest.java index 3302796ab709f..db85ee1feffe9 100644 --- a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/generative/GenerativeForkRestTest.java +++ b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/generative/GenerativeForkRestTest.java @@ -18,7 +18,7 @@ import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.APPROXIMATION_V4; import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.FORK_V9; import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.METRICS_GROUP_BY_ALL; -import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2; +import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.OPTIONAL_FIELDS_V3; import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.SUBQUERY_IN_FROM_COMMAND; import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.UNMAPPED_FIELDS; import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.VIEWS_WITH_BRANCHING; @@ -66,7 +66,7 @@ protected void shouldSkipTest(String testName) throws IOException { // FORK is not supported with unmapped_fields="load", see https://github.com/elastic/elasticsearch/issues/142033 assumeFalse( "FORK is not supported with unmapped_fields=\"load\"", - testCase.requiredCapabilities.contains(OPTIONAL_FIELDS_V2.capabilityName()) + testCase.requiredCapabilities.contains(OPTIONAL_FIELDS_V3.capabilityName()) ); assumeFalse( diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/flattened.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/flattened.csv-spec index 2f2946d4dcbf1..f6b3d482a04df 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/flattened.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/flattened.csv-spec @@ -1,6 +1,6 @@ flattened root fields required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs @@ -16,7 +16,7 @@ FROM flattened_otel_logs // ---------------------------------------------------- flattened KEEP subfield required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs @@ -40,7 +40,7 @@ FROM flattened_otel_logs // ---------------------------------------------------- flattened DROP subfield required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs @@ -65,7 +65,7 @@ FROM flattened_otel_logs // ---------------------------------------------------- flattened DROP subfield after KEEP required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs @@ -90,7 +90,7 @@ FROM flattened_otel_logs // ---------------------------------------------------- flattened subfield with WHERE required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs @@ -106,7 +106,7 @@ FROM flattened_otel_logs // ---------------------------------------------------- flattened subfield with WHERE and KEEP * required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs @@ -123,7 +123,7 @@ FROM flattened_otel_logs // ---------------------------------------------------- flattened subfield with WHERE and KEEP specific subfields required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs @@ -140,7 +140,7 @@ FROM flattened_otel_logs // ---------------------------------------------------- flattened subfield with EVAL TO_UPPER required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs @@ -165,7 +165,7 @@ FROM flattened_otel_logs // ---------------------------------------------------- flattened subfield with EVAL LENGTH required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs @@ -190,7 +190,7 @@ FROM flattened_otel_logs // ---------------------------------------------------- SORT on flattened subfield required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs @@ -214,7 +214,7 @@ FROM flattened_otel_logs // ---------------------------------------------------- RENAME flattened subfield required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs @@ -239,7 +239,7 @@ FROM flattened_otel_logs // ---------------------------------------------------- flattened subfield with STATS count required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs @@ -253,7 +253,7 @@ count(*):long | resource.attributes.agent.type:keyword // ---------------------------------------------------- flattened subfield with STATS count_distinct required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs @@ -267,7 +267,7 @@ count_distinct(resource.attributes.host.name):long // ---------------------------------------------------- flattened subfield with INLINE STATS required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs @@ -288,7 +288,7 @@ FROM flattened_otel_logs // ---------------------------------------------------- flattened subfield with MV_EXPAND required_capability: load_flattened_field -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM flattened_otel_logs diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index 4c5ffb9b522f3..947084926bbcb 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -3,7 +3,7 @@ #################### // These ones verify we don't do anything extra when unmapped_fields is not set to "load" doesNotLoadUnmappedFieldsSort -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 FROM partial_mapping_sample_data | SORT @timestamp DESC @@ -20,7 +20,7 @@ FROM partial_mapping_sample_data ; doesNotLoadUnmappedFieldsStats -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 FROM partial_mapping_sample_data | STATS count(*) BY message @@ -36,7 +36,7 @@ count(*):long | message:keyword ; doesNotLoadUnmappedFieldsInlineStats -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 FROM partial_mapping_sample_data | INLINE STATS count = COUNT(*) BY message @@ -51,7 +51,7 @@ FROM partial_mapping_sample_data ; doesNotLoadUnmappedFieldsInlineStatsNoGrouping -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 FROM partial_mapping_sample_data | INLINE STATS max_duration = MAX(event_duration) @@ -66,7 +66,7 @@ FROM partial_mapping_sample_data ; doesNotLoadUnmappedFieldsEnrich -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: enrich_load FROM partial_mapping_sample_data @@ -84,7 +84,7 @@ FROM partial_mapping_sample_data doesNotLoadUnmappedFieldsLookupJoin-Ignore // temporarily forbidding "load" with LOOKUP JOIN -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: join_lookup_v12 FROM partial_mapping_sample_data @@ -105,7 +105,7 @@ FROM partial_mapping_sample_data ###################### unmappedFieldDoesNotAppearLast -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -118,7 +118,7 @@ FROM partial_mapping_sample_data ; fieldDoesNotExistSingleIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -137,7 +137,7 @@ FROM partial_mapping_sample_data ; fieldIsUnmappedSingleIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -156,7 +156,7 @@ FROM partial_mapping_sample_data ; fieldUnmappedInSourceButExcludedSingleIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: source_field_mapping SET unmapped_fields="load"\; @@ -176,7 +176,7 @@ FROM partial_mapping_excluded_source_sample_data ; fieldUnmappedInSourceButSourceDisabledSingleIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: source_field_mapping SET unmapped_fields="load"\; @@ -196,7 +196,7 @@ FROM partial_mapping_no_source_sample_data ; statsByUnmappedFieldExistsInSource -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -213,7 +213,7 @@ s:long | c:long | unmapped_message:keyword ; inlineStatsByUnmappedFieldExistsInSource -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -231,7 +231,7 @@ FROM partial_mapping_sample_data ; unmappedFieldNonExistentTsIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: ts_command_v0 SET unmapped_fields="load"\; @@ -250,7 +250,7 @@ FROM k8s_unmapped ; statsImplicitLastOverTimeUnmappedTsIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: ts_command_v0 SET unmapped_fields="load"\; @@ -268,7 +268,7 @@ time_bucket:datetime | x:keyword ; statsByUnmappedFieldTsIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: ts_command_v0 SET unmapped_fields="load"\; @@ -293,7 +293,7 @@ s:long | c:long | event_log:keyword ; explicitLastOverTimeUnmappedTsIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: ts_command_v0 SET unmapped_fields="load"\; @@ -313,7 +313,7 @@ qa | 2024-05-10T00:10:00.000Z | vulputate qu ; fieldIsNestedAndUnmapped -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -332,7 +332,7 @@ FROM partial_mapping_sample_data ; fieldIsNestedAndNonExistent -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -355,7 +355,7 @@ FROM partial_mapping_sample_data ############################### noFieldExistsMultiParametersSingleIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -374,7 +374,7 @@ FROM partial_mapping_sample_data ; mixedFieldsMultiParametersSingleIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -397,7 +397,7 @@ FROM partial_mapping_sample_data ##################### mixedFieldsMultiParametersMultiIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data, sample_data METADATA _index @@ -423,7 +423,7 @@ sample_data | 2023-10-23T12:15:03.360Z | null | Connected ; fieldDoesNotExistMultiIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data, sample_data METADATA _index @@ -449,7 +449,7 @@ sample_data | 2023-10-23T12:15:03.360Z | null ; fieldIsUnmappedMultiIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data, sample_data METADATA _index @@ -475,7 +475,7 @@ FROM partial_mapping_sample_data, sample_data METADATA _index ; fieldIsPartiallyUnmappedMultiIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data METADATA _index @@ -501,7 +501,7 @@ sample_data | Connected to 10.1.0.1 ; fieldIsPartiallyUnmappedAndRenamedMultiIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data @@ -527,735 +527,8 @@ Connected to 10.1.0.1 42 ; -partiallyUnmappedNonKeyword -required_capability: optional_fields_v2 -required_capability: index_metadata_field - -SET unmapped_fields="load"\; -FROM sample_data, no_mapping_sample_data METADATA _index -| EVAL event_duration = event_duration::DOUBLE -| KEEP _index, event_duration -| SORT _index, event_duration -; - -_index:keyword | event_duration:double -no_mapping_sample_data | 725447.0 -no_mapping_sample_data | 1232381.0 -no_mapping_sample_data | 1756466.0 -no_mapping_sample_data | 2764888.0 -no_mapping_sample_data | 3450232.0 -no_mapping_sample_data | 5033754.0 -no_mapping_sample_data | 8268152.0 -sample_data | 725448.0 -sample_data | 1232382.0 -sample_data | 1756467.0 -sample_data | 2764889.0 -sample_data | 3450233.0 -sample_data | 5033755.0 -sample_data | 8268153.0 -; - -partiallyUnmappedNonKeywordNoExistence -required_capability: optional_fields_v2 - -SET unmapped_fields="load"\; -FROM sample_data, no_mapping_sample_data, colors METADATA _index -| EVAL event_duration = event_duration::DOUBLE -| KEEP _index, event_duration -| SORT _index DESC, event_duration -| LIMIT 18 -; - -_index:keyword | event_duration:double -sample_data | 725448.0 -sample_data | 1232382.0 -sample_data | 1756467.0 -sample_data | 2764889.0 -sample_data | 3450233.0 -sample_data | 5033755.0 -sample_data | 8268153.0 -no_mapping_sample_data | 725447.0 -no_mapping_sample_data | 1232381.0 -no_mapping_sample_data | 1756466.0 -no_mapping_sample_data | 2764888.0 -no_mapping_sample_data | 3450232.0 -no_mapping_sample_data | 5033754.0 -no_mapping_sample_data | 8268152.0 -colors | null -colors | null -colors | null -colors | null -; - -partiallyUnmappedMixedTypes -required_capability: optional_fields_v2 -required_capability: index_metadata_field - -SET unmapped_fields="load"\; -FROM sample_data, logs, no_mapping_sample_data METADATA _index -| EVAL message = message::KEYWORD, @timestamp = @timestamp :: date -| KEEP _index, @timestamp, message -| SORT _index, @timestamp DESC -; - -_index:keyword | @timestamp:date | message:keyword -logs | 2023-10-23T13:57:01.544Z | Running cats (cycle 3) -logs | 2023-10-23T13:56:01.544Z | Running cats (cycle 2) -logs | 2023-10-23T13:56:01.543Z | No response -logs | 2023-10-23T13:55:01.546Z | More java stuff -logs | 2023-10-23T13:55:01.545Z | Doing java stuff for 192.168.86.038 -logs | 2023-10-23T13:55:01.544Z | Running cats (cycle 1) -logs | 2023-10-23T13:55:01.543Z | Pinging 192.168.86.046 -no_mapping_sample_data | 2024-10-23T13:55:01.543Z | Connected to 10.1.0.1! -no_mapping_sample_data | 2024-10-23T13:53:55.832Z | Connection error? -no_mapping_sample_data | 2024-10-23T13:52:55.015Z | Connection error? -no_mapping_sample_data | 2024-10-23T13:51:54.732Z | Connection error? -no_mapping_sample_data | 2024-10-23T13:33:34.937Z | 42 -no_mapping_sample_data | 2024-10-23T12:27:28.948Z | Connected to 10.1.0.2! -no_mapping_sample_data | 2024-10-23T12:15:03.360Z | Connected to 10.1.0.3! -sample_data | 2023-10-23T13:55:01.543Z | Connected to 10.1.0.1 -sample_data | 2023-10-23T13:53:55.832Z | Connection error -sample_data | 2023-10-23T13:52:55.015Z | Connection error -sample_data | 2023-10-23T13:51:54.732Z | Connection error -sample_data | 2023-10-23T13:33:34.937Z | Disconnected -sample_data | 2023-10-23T12:27:28.948Z | Connected to 10.1.0.2 -sample_data | 2023-10-23T12:15:03.360Z | Connected to 10.1.0.3 -; - -####################### -# Type conflict tests # -####################### - -typeConflictKeywordUnmappedCastToKeyword -required_capability: optional_fields_v2 - -SET unmapped_fields="load"\; -FROM sample_data, no_mapping_sample_data METADATA _index -| EVAL message = message::keyword -| KEEP _index, message -| SORT _index, message -; - -_index:keyword | message:keyword -no_mapping_sample_data | 42 -no_mapping_sample_data | Connected to 10.1.0.1! -no_mapping_sample_data | Connected to 10.1.0.2! -no_mapping_sample_data | Connected to 10.1.0.3! -no_mapping_sample_data | Connection error? -no_mapping_sample_data | Connection error? -no_mapping_sample_data | Connection error? -sample_data | Connected to 10.1.0.1 -sample_data | Connected to 10.1.0.2 -sample_data | Connected to 10.1.0.3 -sample_data | Connection error -sample_data | Connection error -sample_data | Connection error -sample_data | Disconnected -; - -typeConflictLongUnmappedCastToKeyword -required_capability: optional_fields_v2 - -SET unmapped_fields="load"\; -FROM sample_data, no_mapping_sample_data METADATA _index -| EVAL event_duration = event_duration::keyword -| KEEP _index, event_duration -| SORT _index, event_duration -; - -_index:keyword | event_duration:keyword -no_mapping_sample_data | 1232381 -no_mapping_sample_data | 1756466 -no_mapping_sample_data | 2764888 -no_mapping_sample_data | 3450232 -no_mapping_sample_data | 5033754 -no_mapping_sample_data | 725447 -no_mapping_sample_data | 8268152 -sample_data | 1232382 -sample_data | 1756467 -sample_data | 2764889 -sample_data | 3450233 -sample_data | 5033755 -sample_data | 725448 -sample_data | 8268153 -; - -typeConflictLongUnmappedCastToLong -required_capability: optional_fields_v2 - -SET unmapped_fields="load"\; -FROM sample_data, no_mapping_sample_data METADATA _index -| EVAL event_duration = event_duration::long -| KEEP _index, event_duration -| SORT _index, event_duration -; - -_index:keyword | event_duration:long -no_mapping_sample_data | 725447 -no_mapping_sample_data | 1232381 -no_mapping_sample_data | 1756466 -no_mapping_sample_data | 2764888 -no_mapping_sample_data | 3450232 -no_mapping_sample_data | 5033754 -no_mapping_sample_data | 8268152 -sample_data | 725448 -sample_data | 1232382 -sample_data | 1756467 -sample_data | 2764889 -sample_data | 3450233 -sample_data | 5033755 -sample_data | 8268153 -; - -typeConflictLongUnmappedCastToDouble -required_capability: optional_fields_v2 - -SET unmapped_fields="load"\; -FROM sample_data, no_mapping_sample_data METADATA _index -| EVAL event_duration = event_duration::double -| KEEP _index, event_duration -| SORT _index, event_duration -; - -_index:keyword | event_duration:double -no_mapping_sample_data | 725447.0 -no_mapping_sample_data | 1232381.0 -no_mapping_sample_data | 1756466.0 -no_mapping_sample_data | 2764888.0 -no_mapping_sample_data | 3450232.0 -no_mapping_sample_data | 5033754.0 -no_mapping_sample_data | 8268152.0 -sample_data | 725448.0 -sample_data | 1232382.0 -sample_data | 1756467.0 -sample_data | 2764889.0 -sample_data | 3450233.0 -sample_data | 5033755.0 -sample_data | 8268153.0 -; - -############################# -# Mapped and non-existent # -############################# - -typeConflictKeywordNonExistentNoCast -required_capability: optional_fields_v2 - -SET unmapped_fields="load"\; -FROM sample_data, colors METADATA _index -| KEEP _index, message -| SORT _index DESC, message -| LIMIT 15 -; - -_index:keyword | message:keyword -sample_data | Connected to 10.1.0.1 -sample_data | Connected to 10.1.0.2 -sample_data | Connected to 10.1.0.3 -sample_data | Connection error -sample_data | Connection error -sample_data | Connection error -sample_data | Disconnected -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -; - -typeConflictKeywordNonExistentCastToKeyword -required_capability: optional_fields_v2 - -SET unmapped_fields="load"\; -FROM sample_data, colors METADATA _index -| EVAL message = message::keyword -| KEEP _index, message -| SORT _index DESC, message -| LIMIT 15 -; - -_index:keyword | message:keyword -sample_data | Connected to 10.1.0.1 -sample_data | Connected to 10.1.0.2 -sample_data | Connected to 10.1.0.3 -sample_data | Connection error -sample_data | Connection error -sample_data | Connection error -sample_data | Disconnected -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -; - -typeConflictLongNonExistentCastToKeyword -required_capability: optional_fields_v2 - -SET unmapped_fields="load"\; -FROM sample_data, colors METADATA _index -| EVAL event_duration = event_duration::keyword -| KEEP _index, event_duration -| SORT _index DESC, event_duration -| LIMIT 15 -; - -_index:keyword | event_duration:keyword -sample_data | 1232382 -sample_data | 1756467 -sample_data | 2764889 -sample_data | 3450233 -sample_data | 5033755 -sample_data | 725448 -sample_data | 8268153 -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -; - -typeConflictLongNonExistentCastToLong -required_capability: optional_fields_v2 - -SET unmapped_fields="load"\; -FROM sample_data, colors METADATA _index -| EVAL event_duration = event_duration::long -| KEEP _index, event_duration -| SORT _index DESC, event_duration -| LIMIT 15 -; - -_index:keyword | event_duration:long -sample_data | 725448 -sample_data | 1232382 -sample_data | 1756467 -sample_data | 2764889 -sample_data | 3450233 -sample_data | 5033755 -sample_data | 8268153 -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -; - -typeConflictLongNonExistentCastToDouble -required_capability: optional_fields_v2 - -SET unmapped_fields="load"\; -FROM sample_data, colors METADATA _index -| EVAL event_duration = event_duration::double -| KEEP _index, event_duration -| SORT _index DESC, event_duration -| LIMIT 15 -; - -_index:keyword | event_duration:double -sample_data | 725448.0 -sample_data | 1232382.0 -sample_data | 1756467.0 -sample_data | 2764889.0 -sample_data | 3450233.0 -sample_data | 5033755.0 -sample_data | 8268153.0 -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -; - -################################# -# Mapped x 2 and unmapped # -################################# - -typeConflictLongDateUnmappedCastToKeyword -required_capability: optional_fields_v2 -required_capability: index_metadata_field - -SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index -| EVAL ts = @timestamp::keyword -| KEEP _index, ts -| SORT _index, ts -; - -_index:keyword | ts:keyword -no_mapping_sample_data | 2024-10-23T12:15:03.360Z -no_mapping_sample_data | 2024-10-23T12:27:28.948Z -no_mapping_sample_data | 2024-10-23T13:33:34.937Z -no_mapping_sample_data | 2024-10-23T13:51:54.732Z -no_mapping_sample_data | 2024-10-23T13:52:55.015Z -no_mapping_sample_data | 2024-10-23T13:53:55.832Z -no_mapping_sample_data | 2024-10-23T13:55:01.543Z -sample_data | 2023-10-23T12:15:03.360Z -sample_data | 2023-10-23T12:27:28.948Z -sample_data | 2023-10-23T13:33:34.937Z -sample_data | 2023-10-23T13:51:54.732Z -sample_data | 2023-10-23T13:52:55.015Z -sample_data | 2023-10-23T13:53:55.832Z -sample_data | 2023-10-23T13:55:01.543Z -sample_data_ts_long | 1698063303360 -sample_data_ts_long | 1698064048948 -sample_data_ts_long | 1698068014937 -sample_data_ts_long | 1698069114732 -sample_data_ts_long | 1698069175015 -sample_data_ts_long | 1698069235832 -sample_data_ts_long | 1698069301543 -; - -typeConflictLongDateUnmappedCastToDouble -required_capability: optional_fields_v2 -required_capability: index_metadata_field - -SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index -| EVAL d = event_duration::double -| KEEP _index, d -| SORT _index, d -; - -_index:keyword | d:double -no_mapping_sample_data | 725447.0 -no_mapping_sample_data | 1232381.0 -no_mapping_sample_data | 1756466.0 -no_mapping_sample_data | 2764888.0 -no_mapping_sample_data | 3450232.0 -no_mapping_sample_data | 5033754.0 -no_mapping_sample_data | 8268152.0 -sample_data | 725448.0 -sample_data | 1232382.0 -sample_data | 1756467.0 -sample_data | 2764889.0 -sample_data | 3450233.0 -sample_data | 5033755.0 -sample_data | 8268153.0 -sample_data_ts_long | 725448.0 -sample_data_ts_long | 1232382.0 -sample_data_ts_long | 1756467.0 -sample_data_ts_long | 2764889.0 -sample_data_ts_long | 3450233.0 -sample_data_ts_long | 5033755.0 -sample_data_ts_long | 8268153.0 -; - -typeConflictLongDateUnmappedCastToDate -required_capability: optional_fields_v2 -required_capability: index_metadata_field - -SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index -| EVAL ts = @timestamp::date -| KEEP _index, ts -| SORT _index, ts -; - -_index:keyword | ts:date -no_mapping_sample_data | 2024-10-23T12:15:03.360Z -no_mapping_sample_data | 2024-10-23T12:27:28.948Z -no_mapping_sample_data | 2024-10-23T13:33:34.937Z -no_mapping_sample_data | 2024-10-23T13:51:54.732Z -no_mapping_sample_data | 2024-10-23T13:52:55.015Z -no_mapping_sample_data | 2024-10-23T13:53:55.832Z -no_mapping_sample_data | 2024-10-23T13:55:01.543Z -sample_data | 2023-10-23T12:15:03.360Z -sample_data | 2023-10-23T12:27:28.948Z -sample_data | 2023-10-23T13:33:34.937Z -sample_data | 2023-10-23T13:51:54.732Z -sample_data | 2023-10-23T13:52:55.015Z -sample_data | 2023-10-23T13:53:55.832Z -sample_data | 2023-10-23T13:55:01.543Z -sample_data_ts_long | 2023-10-23T12:15:03.360Z -sample_data_ts_long | 2023-10-23T12:27:28.948Z -sample_data_ts_long | 2023-10-23T13:33:34.937Z -sample_data_ts_long | 2023-10-23T13:51:54.732Z -sample_data_ts_long | 2023-10-23T13:52:55.015Z -sample_data_ts_long | 2023-10-23T13:53:55.832Z -sample_data_ts_long | 2023-10-23T13:55:01.543Z -; - -############################################# -# Mapped x 2 and non-existent # -############################################# - -typeConflictLongDateNonExistentCastToKeyword -required_capability: optional_fields_v2 -required_capability: index_metadata_field - -SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, colors METADATA _index -| EVAL ts = @timestamp::keyword -| KEEP _index, ts -| SORT _index DESC, ts -| LIMIT 25 -; - -_index:keyword | ts:keyword -sample_data_ts_long | 1698063303360 -sample_data_ts_long | 1698064048948 -sample_data_ts_long | 1698068014937 -sample_data_ts_long | 1698069114732 -sample_data_ts_long | 1698069175015 -sample_data_ts_long | 1698069235832 -sample_data_ts_long | 1698069301543 -sample_data | 2023-10-23T12:15:03.360Z -sample_data | 2023-10-23T12:27:28.948Z -sample_data | 2023-10-23T13:33:34.937Z -sample_data | 2023-10-23T13:51:54.732Z -sample_data | 2023-10-23T13:52:55.015Z -sample_data | 2023-10-23T13:53:55.832Z -sample_data | 2023-10-23T13:55:01.543Z -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -; - -typeConflictLongDateNonExistentCastToDouble -required_capability: optional_fields_v2 -required_capability: index_metadata_field - -SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, colors METADATA _index -| EVAL ts = @timestamp::double -| KEEP _index, ts -| SORT _index DESC, ts -| LIMIT 25 -; - -_index:keyword | ts:double -sample_data_ts_long | 1.69806330336E12 -sample_data_ts_long | 1.698064048948E12 -sample_data_ts_long | 1.698068014937E12 -sample_data_ts_long | 1.698069114732E12 -sample_data_ts_long | 1.698069175015E12 -sample_data_ts_long | 1.698069235832E12 -sample_data_ts_long | 1.698069301543E12 -sample_data | 1.69806330336E12 -sample_data | 1.698064048948E12 -sample_data | 1.698068014937E12 -sample_data | 1.698069114732E12 -sample_data | 1.698069175015E12 -sample_data | 1.698069235832E12 -sample_data | 1.698069301543E12 -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -; - -typeConflictLongDateNonExistentCastToDate -required_capability: optional_fields_v2 -required_capability: index_metadata_field - -SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, colors METADATA _index -| EVAL ts = @timestamp::date -| KEEP _index, ts -| SORT _index DESC, ts -| LIMIT 25 -; - -_index:keyword | ts:datetime -sample_data_ts_long | 2023-10-23T12:15:03.360Z -sample_data_ts_long | 2023-10-23T12:27:28.948Z -sample_data_ts_long | 2023-10-23T13:33:34.937Z -sample_data_ts_long | 2023-10-23T13:51:54.732Z -sample_data_ts_long | 2023-10-23T13:52:55.015Z -sample_data_ts_long | 2023-10-23T13:53:55.832Z -sample_data_ts_long | 2023-10-23T13:55:01.543Z -sample_data | 2023-10-23T12:15:03.360Z -sample_data | 2023-10-23T12:27:28.948Z -sample_data | 2023-10-23T13:33:34.937Z -sample_data | 2023-10-23T13:51:54.732Z -sample_data | 2023-10-23T13:52:55.015Z -sample_data | 2023-10-23T13:53:55.832Z -sample_data | 2023-10-23T13:55:01.543Z -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -; - -##################################################### -# Mapped x 2, unmapped and non-existent (4 indices) # -##################################################### - -typeConflictLongDateUnmappedNonExistentCastToKeyword -required_capability: optional_fields_v2 -required_capability: index_metadata_field - -SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, no_mapping_sample_data, colors METADATA _index -| EVAL ts = @timestamp::keyword -| KEEP _index, ts -| SORT _index DESC, ts -| LIMIT 30 -; - -_index:keyword | ts:keyword -sample_data_ts_long | 1698063303360 -sample_data_ts_long | 1698064048948 -sample_data_ts_long | 1698068014937 -sample_data_ts_long | 1698069114732 -sample_data_ts_long | 1698069175015 -sample_data_ts_long | 1698069235832 -sample_data_ts_long | 1698069301543 -sample_data | 2023-10-23T12:15:03.360Z -sample_data | 2023-10-23T12:27:28.948Z -sample_data | 2023-10-23T13:33:34.937Z -sample_data | 2023-10-23T13:51:54.732Z -sample_data | 2023-10-23T13:52:55.015Z -sample_data | 2023-10-23T13:53:55.832Z -sample_data | 2023-10-23T13:55:01.543Z -no_mapping_sample_data | 2024-10-23T12:15:03.360Z -no_mapping_sample_data | 2024-10-23T12:27:28.948Z -no_mapping_sample_data | 2024-10-23T13:33:34.937Z -no_mapping_sample_data | 2024-10-23T13:51:54.732Z -no_mapping_sample_data | 2024-10-23T13:52:55.015Z -no_mapping_sample_data | 2024-10-23T13:53:55.832Z -no_mapping_sample_data | 2024-10-23T13:55:01.543Z -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -; - -typeConflictLongDateUnmappedNonExistentCastToDouble -required_capability: optional_fields_v2 -required_capability: index_metadata_field - -SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, no_mapping_sample_data, colors METADATA _index -| EVAL d = event_duration::double -| KEEP _index, d -| SORT _index DESC, d -| LIMIT 30 -; - -_index:keyword | d:double -sample_data_ts_long | 725448.0 -sample_data_ts_long | 1232382.0 -sample_data_ts_long | 1756467.0 -sample_data_ts_long | 2764889.0 -sample_data_ts_long | 3450233.0 -sample_data_ts_long | 5033755.0 -sample_data_ts_long | 8268153.0 -sample_data | 725448.0 -sample_data | 1232382.0 -sample_data | 1756467.0 -sample_data | 2764889.0 -sample_data | 3450233.0 -sample_data | 5033755.0 -sample_data | 8268153.0 -no_mapping_sample_data | 725447.0 -no_mapping_sample_data | 1232381.0 -no_mapping_sample_data | 1756466.0 -no_mapping_sample_data | 2764888.0 -no_mapping_sample_data | 3450232.0 -no_mapping_sample_data | 5033754.0 -no_mapping_sample_data | 8268152.0 -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -; - -typeConflictLongDateUnmappedNonExistentCastToDate -required_capability: optional_fields_v2 -required_capability: index_metadata_field - -SET unmapped_fields="load"\; -FROM sample_data_ts_long, sample_data, no_mapping_sample_data, colors METADATA _index -| EVAL ts = @timestamp::date -| KEEP _index, ts -| SORT _index DESC, ts -| LIMIT 30 -; - -_index:keyword | ts:datetime -sample_data_ts_long | 2023-10-23T12:15:03.360Z -sample_data_ts_long | 2023-10-23T12:27:28.948Z -sample_data_ts_long | 2023-10-23T13:33:34.937Z -sample_data_ts_long | 2023-10-23T13:51:54.732Z -sample_data_ts_long | 2023-10-23T13:52:55.015Z -sample_data_ts_long | 2023-10-23T13:53:55.832Z -sample_data_ts_long | 2023-10-23T13:55:01.543Z -sample_data | 2023-10-23T12:15:03.360Z -sample_data | 2023-10-23T12:27:28.948Z -sample_data | 2023-10-23T13:33:34.937Z -sample_data | 2023-10-23T13:51:54.732Z -sample_data | 2023-10-23T13:52:55.015Z -sample_data | 2023-10-23T13:53:55.832Z -sample_data | 2023-10-23T13:55:01.543Z -no_mapping_sample_data | 2024-10-23T12:15:03.360Z -no_mapping_sample_data | 2024-10-23T12:27:28.948Z -no_mapping_sample_data | 2024-10-23T13:33:34.937Z -no_mapping_sample_data | 2024-10-23T13:51:54.732Z -no_mapping_sample_data | 2024-10-23T13:52:55.015Z -no_mapping_sample_data | 2024-10-23T13:53:55.832Z -no_mapping_sample_data | 2024-10-23T13:55:01.543Z -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -colors | null -; - fieldIsPartiallyUnmappedPartiallySourceIsDisabledMultiIndex -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: source_field_mapping SET unmapped_fields="load"\; @@ -1282,7 +555,7 @@ partial_mapping_sample_data | 2024-10-23T13:55:01.543Z | Connected to ; partialMappingStats -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: source_field_mapping SET unmapped_fields="load"\; @@ -1301,7 +574,7 @@ max(@timestamp):date | count(*):long | message:keyword ; partialMappingCoalesce -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: source_field_mapping SET unmapped_fields="load"\; @@ -1330,7 +603,7 @@ FROM partial_mapping_sample_data,partial_mapping_excluded_source_sample_data MET ; partialMappingKeywordCast -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: source_field_mapping SET unmapped_fields="load"\; @@ -1358,7 +631,7 @@ FROM partial_mapping_sample_data,partial_mapping_excluded_source_sample_data MET ; partialMappingStatsAfterCast -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: source_field_mapping SET unmapped_fields="load"\; @@ -1374,7 +647,7 @@ count(*):long | message::INT:integer ; filterOnPartiallyUnmappedField -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data METADATA _index @@ -1393,7 +666,7 @@ sample_data | Connection error ; sortOnPartiallyUnmappedField -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data METADATA _index @@ -1411,7 +684,7 @@ no_mapping_sample_data | Connected to 10.1.0.2! ; filterOnFullyUnmappedField -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -1427,7 +700,7 @@ FROM partial_mapping_sample_data ; filterOnConjunctionMappedAndUnmapped -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -1443,7 +716,7 @@ FROM partial_mapping_sample_data ; filterOnConjunctionMappedAndNonExistent -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data METADATA _index @@ -1455,7 +728,7 @@ _index:keyword | message:keyword | does_not_exist:keyword ; filterOnDisjunctionMappedAndUnmapped -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -1472,7 +745,7 @@ FROM partial_mapping_sample_data ; filterOnDisjunctionMappedAndNonExistent -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data METADATA _index @@ -1488,7 +761,7 @@ sample_data | Connection error | null ; sortOnNonExistentField -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM no_mapping_sample_data METADATA _index @@ -1506,7 +779,7 @@ no_mapping_sample_data | null ; sortOnUnmappedField -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -1523,7 +796,7 @@ FROM partial_mapping_sample_data ; sortOnExpressionOnUnmappedField -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -1541,7 +814,7 @@ FROM partial_mapping_sample_data ; sortOnMultipleFieldsWithNonExistent -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data METADATA _index @@ -1559,7 +832,7 @@ no_mapping_sample_data | Connected to 10.1.0.2! | null ; sortOnMultipleFieldsWithUnmapped -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -1577,7 +850,7 @@ FROM partial_mapping_sample_data ; filterOnNonExistentFieldCastToLong -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM sample_data, no_mapping_sample_data METADATA _index @@ -1589,7 +862,7 @@ _index:keyword | message:keyword | does_not_exist:keyword ; filterOnUnmappedFieldCastToLong -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 SET unmapped_fields="load"\; FROM partial_mapping_sample_data @@ -1602,7 +875,7 @@ FROM partial_mapping_sample_data ; maxOverTimeOfKeyword -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: ts_command_v0 SET unmapped_fields="load"\; @@ -1626,7 +899,7 @@ us | 2024-05-10T00:04:00.000Z | k8s_unmapped // https://github.com/elastic/elasticsearch/issues/143991 statsFilteredAggAfterEvalWithDottedUnmappedField -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: optional_fields_detect_unmapped_fields_in_agg_filters SET unmapped_fields="load"\; @@ -1641,7 +914,7 @@ null | foo // https://github.com/elastic/elasticsearch/issues/143991 statsFilteredAggAfterEvalWithDottedUnmappedFieldLoadsFromSource -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: optional_fields_detect_unmapped_fields_in_agg_filters SET unmapped_fields="load"\; diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec new file mode 100644 index 0000000000000..98948032dd696 --- /dev/null +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec @@ -0,0 +1,803 @@ +// This test file covers type conflict resolution with unmapped fields, which is similar to union types. + +###################################### +# Mapped and unmapped conflict tests # +###################################### + +noTypeConflictKeywordUnmappedCastToKeyword +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| KEEP _index, message +| SORT _index, message +; + +_index:keyword | message:keyword +no_mapping_sample_data | 42 +no_mapping_sample_data | Connected to 10.1.0.1! +no_mapping_sample_data | Connected to 10.1.0.2! +no_mapping_sample_data | Connected to 10.1.0.3! +no_mapping_sample_data | Connection error? +no_mapping_sample_data | Connection error? +no_mapping_sample_data | Connection error? +sample_data | Connected to 10.1.0.1 +sample_data | Connected to 10.1.0.2 +sample_data | Connected to 10.1.0.3 +sample_data | Connection error +sample_data | Connection error +sample_data | Connection error +sample_data | Disconnected +; + +noTypeConflictKeywordUnmappedCastToKeywordExplicitEval +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL message = message::keyword +| KEEP _index, message +| SORT _index, message +; + +_index:keyword | message:keyword +no_mapping_sample_data | 42 +no_mapping_sample_data | Connected to 10.1.0.1! +no_mapping_sample_data | Connected to 10.1.0.2! +no_mapping_sample_data | Connected to 10.1.0.3! +no_mapping_sample_data | Connection error? +no_mapping_sample_data | Connection error? +no_mapping_sample_data | Connection error? +sample_data | Connected to 10.1.0.1 +sample_data | Connected to 10.1.0.2 +sample_data | Connected to 10.1.0.3 +sample_data | Connection error +sample_data | Connection error +sample_data | Connection error +sample_data | Disconnected +; + +typeConflictLongUnmappedCastToKeyword +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL event_duration = event_duration::keyword +| KEEP _index, event_duration +| SORT _index, event_duration +; + +_index:keyword | event_duration:keyword +no_mapping_sample_data | 1232381 +no_mapping_sample_data | 1756466 +no_mapping_sample_data | 2764888 +no_mapping_sample_data | 3450232 +no_mapping_sample_data | 5033754 +no_mapping_sample_data | 725447 +no_mapping_sample_data | 8268152 +sample_data | 1232382 +sample_data | 1756467 +sample_data | 2764889 +sample_data | 3450233 +sample_data | 5033755 +sample_data | 725448 +sample_data | 8268153 +; + +typeConflictLongUnmappedCastToLong +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL event_duration = event_duration::long +| KEEP _index, event_duration +| SORT _index, event_duration +; + +_index:keyword | event_duration:long +no_mapping_sample_data | 725447 +no_mapping_sample_data | 1232381 +no_mapping_sample_data | 1756466 +no_mapping_sample_data | 2764888 +no_mapping_sample_data | 3450232 +no_mapping_sample_data | 5033754 +no_mapping_sample_data | 8268152 +sample_data | 725448 +sample_data | 1232382 +sample_data | 1756467 +sample_data | 2764889 +sample_data | 3450233 +sample_data | 5033755 +sample_data | 8268153 +; + +typeConflictLongUnmappedCastToDouble +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL event_duration = event_duration::double +| KEEP _index, event_duration +| SORT _index, event_duration +; + +_index:keyword | event_duration:double +no_mapping_sample_data | 725447.0 +no_mapping_sample_data | 1232381.0 +no_mapping_sample_data | 1756466.0 +no_mapping_sample_data | 2764888.0 +no_mapping_sample_data | 3450232.0 +no_mapping_sample_data | 5033754.0 +no_mapping_sample_data | 8268152.0 +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +; + +typeConflictLongUnmappedCastToDoubleNoSort +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL event_duration = event_duration::double +| KEEP _index, event_duration +; +ignoreOrder:true + +_index:keyword | event_duration:double +no_mapping_sample_data | 725447.0 +no_mapping_sample_data | 1232381.0 +no_mapping_sample_data | 1756466.0 +no_mapping_sample_data | 2764888.0 +no_mapping_sample_data | 3450232.0 +no_mapping_sample_data | 5033754.0 +no_mapping_sample_data | 8268152.0 +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +; + + +########################### +# Mapped and non-existent # +########################### + +noTypeConflictKeywordNonExistentNoCast +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, colors METADATA _index +| KEEP _index, message +| SORT _index DESC, message +| LIMIT 15 +; + +_index:keyword | message:keyword +sample_data | Connected to 10.1.0.1 +sample_data | Connected to 10.1.0.2 +sample_data | Connected to 10.1.0.3 +sample_data | Connection error +sample_data | Connection error +sample_data | Connection error +sample_data | Disconnected +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +; + +noTypeConflictKeywordNonExistentCastToKeyword +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, colors METADATA _index +| EVAL message = message::keyword +| KEEP _index, message +| SORT _index DESC, message +| LIMIT 15 +; + +_index:keyword | message:keyword +sample_data | Connected to 10.1.0.1 +sample_data | Connected to 10.1.0.2 +sample_data | Connected to 10.1.0.3 +sample_data | Connection error +sample_data | Connection error +sample_data | Connection error +sample_data | Disconnected +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +; + +typeConflictLongNonExistentCastToKeyword +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, colors METADATA _index +| EVAL event_duration = event_duration::keyword +| KEEP _index, event_duration +| SORT _index DESC, event_duration +| LIMIT 15 +; + +_index:keyword | event_duration:keyword +sample_data | 1232382 +sample_data | 1756467 +sample_data | 2764889 +sample_data | 3450233 +sample_data | 5033755 +sample_data | 725448 +sample_data | 8268153 +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +; + +typeConflictLongNonExistentCastToLong +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, colors METADATA _index +| EVAL event_duration = event_duration::long +| KEEP _index, event_duration +| SORT _index DESC, event_duration +| LIMIT 15 +; + +_index:keyword | event_duration:long +sample_data | 725448 +sample_data | 1232382 +sample_data | 1756467 +sample_data | 2764889 +sample_data | 3450233 +sample_data | 5033755 +sample_data | 8268153 +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +; + +typeConflictLongNonExistentCastToDouble +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, colors METADATA _index +| EVAL event_duration = event_duration::double +| KEEP _index, event_duration +| SORT _index DESC, event_duration +| LIMIT 15 +; + +_index:keyword | event_duration:double +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +; + +typeConflictLongNonExistentCastToDoubleNoSort +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, heights METADATA _index +| EVAL event_duration = event_duration::double +| KEEP _index, event_duration +; +ignoreOrder:true + +_index:keyword | event_duration:double +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +heights | null +heights | null +heights | null +heights | null +heights | null +; + +########################### +# Mapped x 2 and unmapped # +########################### + +typeConflictLongDateUnmappedCastToKeyword +required_capability: optional_fields_v3 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index +| EVAL ts = @timestamp::keyword +| KEEP _index, ts +| SORT _index, ts +; + +_index:keyword | ts:keyword +no_mapping_sample_data | 2024-10-23T12:15:03.360Z +no_mapping_sample_data | 2024-10-23T12:27:28.948Z +no_mapping_sample_data | 2024-10-23T13:33:34.937Z +no_mapping_sample_data | 2024-10-23T13:51:54.732Z +no_mapping_sample_data | 2024-10-23T13:52:55.015Z +no_mapping_sample_data | 2024-10-23T13:53:55.832Z +no_mapping_sample_data | 2024-10-23T13:55:01.543Z +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +sample_data_ts_long | 1698063303360 +sample_data_ts_long | 1698064048948 +sample_data_ts_long | 1698068014937 +sample_data_ts_long | 1698069114732 +sample_data_ts_long | 1698069175015 +sample_data_ts_long | 1698069235832 +sample_data_ts_long | 1698069301543 +; + +typeConflictLongDateUnmappedCastToDouble +required_capability: optional_fields_v3 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index +| EVAL ts = @timestamp::double +| KEEP _index, ts +| SORT _index, ts +; + +warning:Line 3:13: evaluation of [@timestamp::double] failed, treating result as null. Only first 20 failures recorded. +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T12:15:03.360Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T12:27:28.948Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:33:34.937Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:51:54.732Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:52:55.015Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:53:55.832Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:55:01.543Z] +_index:keyword | ts:double +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +sample_data | 1.69806330336E12 +sample_data | 1.698064048948E12 +sample_data | 1.698068014937E12 +sample_data | 1.698069114732E12 +sample_data | 1.698069175015E12 +sample_data | 1.698069235832E12 +sample_data | 1.698069301543E12 +sample_data_ts_long | 1.69806330336E12 +sample_data_ts_long | 1.698064048948E12 +sample_data_ts_long | 1.698068014937E12 +sample_data_ts_long | 1.698069114732E12 +sample_data_ts_long | 1.698069175015E12 +sample_data_ts_long | 1.698069235832E12 +sample_data_ts_long | 1.698069301543E12 +; + +typeConflictLongDateUnmappedCastToDate +required_capability: optional_fields_v3 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index +| EVAL ts = @timestamp::date +| KEEP _index, ts +| SORT _index, ts +; + +_index:keyword | ts:date +no_mapping_sample_data | 2024-10-23T12:15:03.360Z +no_mapping_sample_data | 2024-10-23T12:27:28.948Z +no_mapping_sample_data | 2024-10-23T13:33:34.937Z +no_mapping_sample_data | 2024-10-23T13:51:54.732Z +no_mapping_sample_data | 2024-10-23T13:52:55.015Z +no_mapping_sample_data | 2024-10-23T13:53:55.832Z +no_mapping_sample_data | 2024-10-23T13:55:01.543Z +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +sample_data_ts_long | 2023-10-23T12:15:03.360Z +sample_data_ts_long | 2023-10-23T12:27:28.948Z +sample_data_ts_long | 2023-10-23T13:33:34.937Z +sample_data_ts_long | 2023-10-23T13:51:54.732Z +sample_data_ts_long | 2023-10-23T13:52:55.015Z +sample_data_ts_long | 2023-10-23T13:53:55.832Z +sample_data_ts_long | 2023-10-23T13:55:01.543Z +; + +typeConflictLongDateUnmappedCastToDateNoSort +required_capability: optional_fields_v3 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index +| EVAL ts = @timestamp::date +| KEEP _index, ts +; +ignoreOrder:true + +_index:keyword | ts:date +no_mapping_sample_data | 2024-10-23T12:15:03.360Z +no_mapping_sample_data | 2024-10-23T12:27:28.948Z +no_mapping_sample_data | 2024-10-23T13:33:34.937Z +no_mapping_sample_data | 2024-10-23T13:51:54.732Z +no_mapping_sample_data | 2024-10-23T13:52:55.015Z +no_mapping_sample_data | 2024-10-23T13:53:55.832Z +no_mapping_sample_data | 2024-10-23T13:55:01.543Z +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +sample_data_ts_long | 2023-10-23T12:15:03.360Z +sample_data_ts_long | 2023-10-23T12:27:28.948Z +sample_data_ts_long | 2023-10-23T13:33:34.937Z +sample_data_ts_long | 2023-10-23T13:51:54.732Z +sample_data_ts_long | 2023-10-23T13:52:55.015Z +sample_data_ts_long | 2023-10-23T13:53:55.832Z +sample_data_ts_long | 2023-10-23T13:55:01.543Z +; + +############################### +# Mapped x 2 and non-existent # +############################### + +typeConflictLongDateNonExistentCastToKeyword +required_capability: optional_fields_v3 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, colors METADATA _index +| EVAL ts = @timestamp::keyword +| KEEP _index, ts +| SORT _index DESC, ts +| LIMIT 25 +; + +_index:keyword | ts:keyword +sample_data_ts_long | 1698063303360 +sample_data_ts_long | 1698064048948 +sample_data_ts_long | 1698068014937 +sample_data_ts_long | 1698069114732 +sample_data_ts_long | 1698069175015 +sample_data_ts_long | 1698069235832 +sample_data_ts_long | 1698069301543 +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +; + +typeConflictLongDateNonExistentCastToDouble +required_capability: optional_fields_v3 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, colors METADATA _index +| EVAL ts = @timestamp::double +| KEEP _index, ts +| SORT _index DESC, ts +| LIMIT 25 +; + +_index:keyword | ts:double +sample_data_ts_long | 1.69806330336E12 +sample_data_ts_long | 1.698064048948E12 +sample_data_ts_long | 1.698068014937E12 +sample_data_ts_long | 1.698069114732E12 +sample_data_ts_long | 1.698069175015E12 +sample_data_ts_long | 1.698069235832E12 +sample_data_ts_long | 1.698069301543E12 +sample_data | 1.69806330336E12 +sample_data | 1.698064048948E12 +sample_data | 1.698068014937E12 +sample_data | 1.698069114732E12 +sample_data | 1.698069175015E12 +sample_data | 1.698069235832E12 +sample_data | 1.698069301543E12 +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +; + +typeConflictLongDateNonExistentCastToDate +required_capability: optional_fields_v3 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, colors METADATA _index +| EVAL ts = @timestamp::date +| KEEP _index, ts +| SORT _index DESC, ts +| LIMIT 25 +; + +_index:keyword | ts:datetime +sample_data_ts_long | 2023-10-23T12:15:03.360Z +sample_data_ts_long | 2023-10-23T12:27:28.948Z +sample_data_ts_long | 2023-10-23T13:33:34.937Z +sample_data_ts_long | 2023-10-23T13:51:54.732Z +sample_data_ts_long | 2023-10-23T13:52:55.015Z +sample_data_ts_long | 2023-10-23T13:53:55.832Z +sample_data_ts_long | 2023-10-23T13:55:01.543Z +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +; + +########################################## +# Mapped x 2, unmapped, and non-existent # +########################################## + +typeConflictLongDateUnmappedNonExistentCastToKeyword +required_capability: optional_fields_v3 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data, colors METADATA _index +| EVAL ts = @timestamp::keyword +| KEEP _index, ts +| SORT _index DESC, ts +| LIMIT 30 +; + +_index:keyword | ts:keyword +sample_data_ts_long | 1698063303360 +sample_data_ts_long | 1698064048948 +sample_data_ts_long | 1698068014937 +sample_data_ts_long | 1698069114732 +sample_data_ts_long | 1698069175015 +sample_data_ts_long | 1698069235832 +sample_data_ts_long | 1698069301543 +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +no_mapping_sample_data | 2024-10-23T12:15:03.360Z +no_mapping_sample_data | 2024-10-23T12:27:28.948Z +no_mapping_sample_data | 2024-10-23T13:33:34.937Z +no_mapping_sample_data | 2024-10-23T13:51:54.732Z +no_mapping_sample_data | 2024-10-23T13:52:55.015Z +no_mapping_sample_data | 2024-10-23T13:53:55.832Z +no_mapping_sample_data | 2024-10-23T13:55:01.543Z +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +; + +typeConflictLongDateUnmappedNonExistentCastToDouble +required_capability: optional_fields_v3 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data, colors METADATA _index +| EVAL ts = @timestamp::double +| KEEP _index, ts +| SORT _index DESC, ts +| LIMIT 30 +; + +warning:Line 3:13: evaluation of [@timestamp::double] failed, treating result as null. Only first 20 failures recorded. +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T12:15:03.360Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T12:27:28.948Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:33:34.937Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:51:54.732Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:52:55.015Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:53:55.832Z] +warning:Line 3:13: org.elasticsearch.xpack.esql.core.InvalidArgumentException: Cannot parse number [2024-10-23T13:55:01.543Z] +_index:keyword | ts:double +sample_data_ts_long | 1.69806330336E12 +sample_data_ts_long | 1.698064048948E12 +sample_data_ts_long | 1.698068014937E12 +sample_data_ts_long | 1.698069114732E12 +sample_data_ts_long | 1.698069175015E12 +sample_data_ts_long | 1.698069235832E12 +sample_data_ts_long | 1.698069301543E12 +sample_data | 1.69806330336E12 +sample_data | 1.698064048948E12 +sample_data | 1.698068014937E12 +sample_data | 1.698069114732E12 +sample_data | 1.698069175015E12 +sample_data | 1.698069235832E12 +sample_data | 1.698069301543E12 +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +no_mapping_sample_data | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +; + +typeConflictLongDateUnmappedNonExistentCastToDate +required_capability: optional_fields_v3 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data, colors METADATA _index +| EVAL ts = @timestamp::date +| KEEP _index, ts +| SORT _index DESC, ts +| LIMIT 30 +; + +_index:keyword | ts:datetime +sample_data_ts_long | 2023-10-23T12:15:03.360Z +sample_data_ts_long | 2023-10-23T12:27:28.948Z +sample_data_ts_long | 2023-10-23T13:33:34.937Z +sample_data_ts_long | 2023-10-23T13:51:54.732Z +sample_data_ts_long | 2023-10-23T13:52:55.015Z +sample_data_ts_long | 2023-10-23T13:53:55.832Z +sample_data_ts_long | 2023-10-23T13:55:01.543Z +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +no_mapping_sample_data | 2024-10-23T12:15:03.360Z +no_mapping_sample_data | 2024-10-23T12:27:28.948Z +no_mapping_sample_data | 2024-10-23T13:33:34.937Z +no_mapping_sample_data | 2024-10-23T13:51:54.732Z +no_mapping_sample_data | 2024-10-23T13:52:55.015Z +no_mapping_sample_data | 2024-10-23T13:53:55.832Z +no_mapping_sample_data | 2024-10-23T13:55:01.543Z +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +colors | null +; + +typeConflictLongDateUnmappedNonExistentCastToDateNoSort +required_capability: optional_fields_v3 +required_capability: index_metadata_field + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data, heights METADATA _index +| EVAL ts = @timestamp::date +| KEEP _index, ts +; +ignoreOrder:true + +_index:keyword | ts:datetime +heights | null +heights | null +heights | null +heights | null +heights | null +no_mapping_sample_data | 2024-10-23T12:15:03.360Z +no_mapping_sample_data | 2024-10-23T12:27:28.948Z +no_mapping_sample_data | 2024-10-23T13:33:34.937Z +no_mapping_sample_data | 2024-10-23T13:51:54.732Z +no_mapping_sample_data | 2024-10-23T13:52:55.015Z +no_mapping_sample_data | 2024-10-23T13:53:55.832Z +no_mapping_sample_data | 2024-10-23T13:55:01.543Z +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +sample_data_ts_long | 2023-10-23T12:15:03.360Z +sample_data_ts_long | 2023-10-23T12:27:28.948Z +sample_data_ts_long | 2023-10-23T13:33:34.937Z +sample_data_ts_long | 2023-10-23T13:51:54.732Z +sample_data_ts_long | 2023-10-23T13:52:55.015Z +sample_data_ts_long | 2023-10-23T13:53:55.832Z +sample_data_ts_long | 2023-10-23T13:55:01.543Z +; diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlActionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlActionIT.java index c6ce22b8f16a5..2ab01cc63ef9b 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlActionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlActionIT.java @@ -2660,7 +2660,7 @@ public void testExplainWithApproximation() { * resulting in null values instead of the actual _source values for unmapped fields. */ public void testUnmappedFieldsLoadWithSingleShardConcurrency() { - assumeTrue("requires unmapped fields load support", EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled()); + assumeTrue("requires unmapped fields load support", EsqlCapabilities.Cap.OPTIONAL_FIELDS_V3.isEnabled()); assertAcked(prepareCreate("test_mapped").setMapping("event_duration", "type=long")); assertAcked(prepareCreate("test_unmapped").setMapping(""" {"dynamic": false, "properties": {}}""")); 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 adf4bd947bcc0..5850a88960748 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 @@ -221,7 +221,7 @@ public enum Cap { /** * Support for optional fields (might or might not be present in the mappings) using FAIL/NULLIFY only. - * Compared to {@link #OPTIONAL_FIELDS_V2}, this does not enable support for LOAD. + * Compared to {@link #OPTIONAL_FIELDS_V3}, this does not enable support for LOAD. */ OPTIONAL_FIELDS_NULLIFY_TECH_PREVIEW, @@ -245,8 +245,9 @@ public enum Cap { /** * Support for optional fields (might or might not be present in the mappings) using FAIL/NULLIFY/LOAD. * V2: prevent pushing down filters and sorts to Lucene of potentially unmapped fields. + * V3: Support for union type like resolution for load. */ - OPTIONAL_FIELDS_V2(Build.current().isSnapshot()), + OPTIONAL_FIELDS_V3(Build.current().isSnapshot()), /** * Support specifically for *just* the _index METADATA field. Used by CsvTests, since that is the only metadata field currently diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index 5be18de76ead9..1cacb8415db84 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -180,7 +180,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.TreeMap; import java.util.TreeSet; import java.util.function.Function; import java.util.function.Predicate; @@ -1209,7 +1208,8 @@ private Attribute resolveInsistAttribute(Attribute attribute, List ch // Field is partially unmapped. // TODO: Should the check for partially unmapped fields be done specific to each sub-query in a fork? if (resolvedCol instanceof FieldAttribute fa && indices.stream().anyMatch(r -> r.get().isPartiallyUnmappedField(fa.name()))) { - return fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa, indices); + // NOTE: We use indices.getFirst() here as a temporary solution. INSIST will be removed after load is in GA anyway. + return fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa, indices.getFirst()); } // Either the field is mapped everywhere and we can just use the resolved column, or the INSIST clause isn't on top of a FROM @@ -1217,27 +1217,9 @@ private Attribute resolveInsistAttribute(Attribute attribute, List ch return resolvedCol; } - private static FieldAttribute invalidInsistAttribute(FieldAttribute fa, List indexResolutions) { - String name = fa.name(); - List unmappedIndices = indexResolutions.stream() - .map(IndexResolution::get) - .filter(r -> r.isPartiallyUnmappedField(name)) - .toList(); - if (unmappedIndices.isEmpty()) { - throw new IllegalStateException(Strings.format("No index with unmapped '%s' found", name)); - } - if (unmappedIndices.size() > 1) { - throw new IllegalStateException( - Strings.format( - "Multiple indices with unmapped '%s' found: %s; Unexpected since we forks/subqueries/etc. are currently disabled!", - name, - unmappedIndices.stream().map(EsIndex::name).toList() - ) - ); - } - EsIndex esIndex = unmappedIndices.getFirst(); - InvalidMappedField field = InvalidMappedField.potentiallyUnmapped(name, getTypesToIndices(fa, esIndex)); - return new FieldAttribute(fa.source(), null, fa.qualifier(), name, field); + private static FieldAttribute invalidInsistAttribute(FieldAttribute fa, IndexResolution indexResolutions) { + InvalidMappedField field = InvalidMappedField.potentiallyUnmapped(fa.name(), getTypesToIndices(fa, indexResolutions.get())); + return new FieldAttribute(fa.source(), null, fa.qualifier(), fa.name(), field); } private static Map> getTypesToIndices(FieldAttribute fa, EsIndex esIndex) { @@ -1247,7 +1229,7 @@ private static Map> getTypesToIndices(FieldAttribute fa, EsI // Field isn't currently invalid, meaning it's mapped to a single type in all the indices where it's actually mapped. TreeSet indicesWithField = new TreeSet<>(esIndex.concreteQualifiedIndices()); indicesWithField.removeAll(esIndex.getUnmappedIndices(fa.name())); - return new TreeMap<>(Map.of(fa.dataType().typeName(), indicesWithField)); + return Map.of(fa.dataType().typeName(), indicesWithField); } public static FieldAttribute insistKeyword(Attribute attribute) { @@ -1266,11 +1248,19 @@ public static FieldAttribute insistKeyword(Attribute attribute) { */ private static LogicalPlan resolvePartiallyMapped(LogicalPlan plan, AnalyzerContext context) { var indexResolutions = collectIndexResolutions(plan, context); + if (indexResolutions.isEmpty()) { + throw new IllegalStateException("Unmapped fields with empty index resolutions."); + } + if (indexResolutions.size() > 1) { + throw new IllegalStateException( + Strings.format("Multiple index patterns should be disabled with unmapped fields", indexResolutions) + ); + } Map insistedMap = new HashMap<>(); var transformed = plan.transformExpressionsOnly(FieldAttribute.class, fa -> { var esField = fa.field(); if (esField instanceof PotentiallyUnmappedKeywordEsField - || (esField instanceof InvalidMappedField imf && imf.isPotentiallyUnmapped())) { + || esField instanceof InvalidMappedField imf && imf.isPotentiallyUnmapped()) { return fa; } var existing = insistedMap.get(fa); @@ -1278,7 +1268,9 @@ private static LogicalPlan resolvePartiallyMapped(LogicalPlan plan, AnalyzerCont return existing; } if (indexResolutions.stream().anyMatch(r -> r.get().isPartiallyUnmappedField(fa.name()))) { - FieldAttribute newFA = fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa, indexResolutions); + FieldAttribute newFA = fa.dataType() == KEYWORD + ? insistKeyword(fa) + : invalidInsistAttribute(fa, indexResolutions.getFirst()); insistedMap.put(fa, newFA); return newFA; } @@ -2495,7 +2487,7 @@ private Expression resolveConvertFunction(ConvertFunction convert, List typeResolutions, + Map typeResolutions, @Nullable Expression potentiallyUnmappedConversion ) { Map typesToConversionExpressions = new HashMap<>(); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/QuerySettings.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/QuerySettings.java index e2fede89460dd..ddabaac19534e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/QuerySettings.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/QuerySettings.java @@ -95,12 +95,12 @@ public class QuerySettings { String resolution = Foldables.stringLiteralValueOf(value, "Unexpected value"); try { UnmappedResolution res = UnmappedResolution.valueOf(resolution.toUpperCase(Locale.ROOT)); - if (res == UnmappedResolution.LOAD && EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled() == false) { + if (res == UnmappedResolution.LOAD && EsqlCapabilities.Cap.OPTIONAL_FIELDS_V3.isEnabled() == false) { throw new IllegalArgumentException("'LOAD' is only supported in snapshot builds"); } return res; } catch (Exception exc) { - var values = EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled() + var values = EsqlCapabilities.Cap.OPTIONAL_FIELDS_V3.isEnabled() ? UnmappedResolution.values() : Arrays.stream(UnmappedResolution.values()).filter(e -> e != UnmappedResolution.LOAD).toArray(); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java index 0b4b5aacffe37..24ef97cb45e09 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java @@ -323,12 +323,6 @@ private static class DefaultShardContextForUnmappedField extends DefaultShardCon return superResult == null && name.equals(unmappedEsField.getName()) ? createUnmappedFieldType(name, this) : superResult; } - @Override - protected Set resolveSourcePaths(String name) { - var result = super.resolveSourcePaths(name); - return result.isEmpty() && name.equals(unmappedEsField.getName()) ? Set.of(name) : result; - } - static MappedFieldType createUnmappedFieldType(String name, DefaultShardContext context) { var builder = new KeywordFieldMapper.Builder(name, context.ctx.getIndexSettings()); builder.docValues(false); @@ -664,10 +658,6 @@ public double storedFieldsSequentialProportion() { return EsqlPlugin.STORED_FIELDS_SEQUENTIAL_PROPORTION.get(ctx.getIndexSettings().getSettings()); } - protected Set resolveSourcePaths(String name) { - return ctx.sourcePath(name); - } - @Override public void close() { releasable.close(); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java index 35c90e3a873ba..c44a8355c6af1 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java @@ -277,7 +277,7 @@ public static LogicalPlan analyzeStatement(String query, boolean checkPlan) { } public static LogicalPlan analyzeStatement(String query, Map indexResolutions) { - return analyzeStatement(query, indexResolutions, false); + return analyzeStatement(query, indexResolutions, true); } public static LogicalPlan analyzeStatement(String query, Map indexResolutions, boolean checkPlan) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index 7cc69869b2350..9ae3f09560a3b 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -789,7 +789,7 @@ private static String setUnmappedNullify(String query) { } private static String setUnmappedLoad(String query) { - assumeTrue("Requires OPTIONAL_FIELDS_V2", EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled()); + assumeTrue("Requires OPTIONAL_FIELDS_V3", EsqlCapabilities.Cap.OPTIONAL_FIELDS_V3.isEnabled()); return "SET unmapped_fields=\"load\"; " + query; } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/UnmappedGoldenTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/UnmappedGoldenTestCase.java index cf3dd01f9d741..f2fa46ed8a90c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/UnmappedGoldenTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/UnmappedGoldenTestCase.java @@ -41,7 +41,7 @@ private Optional tryRunTestsNullifyOnly(String query, EnumSet } private Optional tryRunTestsLoadOnly(String query, EnumSet stages, String... nestedPaths) { - return EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled() + return EsqlCapabilities.Cap.OPTIONAL_FIELDS_V3.isEnabled() ? builder(setUnmappedLoad(query)).nestedPath(ArrayUtils.prepend("load", nestedPaths)).stages(stages).tryRun() : Optional.empty(); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/SetParserTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/SetParserTests.java index 598713ed116b3..f9001f3f58306 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/SetParserTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/SetParserTests.java @@ -199,7 +199,7 @@ private Object settingValue(EsqlStatement query, int position) { } public void testSetUnmappedFields_snapshot() { - assumeTrue("OPTIONAL_FIELDS_V2 option required", EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled()); + assumeTrue("OPTIONAL_FIELDS_V3 option required", EsqlCapabilities.Cap.OPTIONAL_FIELDS_V3.isEnabled()); var modes = List.of("FAIL", "NULLIFY", "LOAD"); verifySetUnmappedFields(modes); @@ -236,7 +236,7 @@ public void testSetUnmappedFieldsWrongValue() { v -> Arrays.stream(UnmappedResolution.values()).anyMatch(x -> x.name().equalsIgnoreCase(v)), () -> randomAlphaOfLengthBetween(0, 10) ); - var values = EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled() + var values = EsqlCapabilities.Cap.OPTIONAL_FIELDS_V3.isEnabled() ? UnmappedResolution.values() : Arrays.stream(UnmappedResolution.values()).filter(e -> e != UnmappedResolution.LOAD).toArray(); expectValidationError( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plan/QuerySettingsTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plan/QuerySettingsTests.java index 6454ed88cbf28..7cc9d41e370ca 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plan/QuerySettingsTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plan/QuerySettingsTests.java @@ -114,7 +114,7 @@ public void testValidate_UnmappedFields_techPreview() { } public void testValidate_UnmappedFields_allValues() { - assumeTrue("Requires unmapped fields", EsqlCapabilities.Cap.OPTIONAL_FIELDS_V2.isEnabled()); + assumeTrue("Requires unmapped fields", EsqlCapabilities.Cap.OPTIONAL_FIELDS_V3.isEnabled()); validateUnmappedFields("FAIL", "NULLIFY", "LOAD"); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/InvalidMappedFieldTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/InvalidMappedFieldTests.java index fc35e940a8c13..e140ef1db8693 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/InvalidMappedFieldTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/InvalidMappedFieldTests.java @@ -12,6 +12,7 @@ import java.util.Map; +// FIXME(gal, NOCOMMIT) Add new boolean property public class InvalidMappedFieldTests extends AbstractEsFieldTypeTests { static InvalidMappedField randomInvalidMappedField(int maxPropertiesDepth) { String name = randomAlphaOfLength(4); From 95ead586d0b2d3a60e139823273c7134ff444254 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Mon, 23 Mar 2026 20:49:52 +0200 Subject: [PATCH 119/137] Update docs/changelog/143693.yaml --- docs/changelog/143693.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/changelog/143693.yaml b/docs/changelog/143693.yaml index a9328ab62bd39..fe3409056366e 100644 --- a/docs/changelog/143693.yaml +++ b/docs/changelog/143693.yaml @@ -1,5 +1,6 @@ area: ES|QL -issues: [] +issues: + - 141912 pr: 143693 summary: Type conflict resolution in unmapped-fields load type: feature From a7f8dbdcfdbe8aedbc309b3374f6dc2a17b6f7ed Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 24 Mar 2026 11:40:25 +0200 Subject: [PATCH 120/137] Update docs/changelog/143693.yaml --- docs/changelog/143693.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog/143693.yaml b/docs/changelog/143693.yaml index fe3409056366e..a65437a2d2caa 100644 --- a/docs/changelog/143693.yaml +++ b/docs/changelog/143693.yaml @@ -1,5 +1,6 @@ area: ES|QL issues: + - 142004 - 141912 pr: 143693 summary: Type conflict resolution in unmapped-fields load From f66e36ee29c3b6da672a93930a10e23794052610 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 24 Mar 2026 13:42:27 +0200 Subject: [PATCH 121/137] Skip load tests in CsvTests --- .../src/test/java/org/elasticsearch/xpack/esql/CsvTests.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java index 6d88aba74f737..3a4b84b67beab 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java @@ -324,6 +324,10 @@ public final void test() throws Throwable { "can't load flattened field values in csv tests", testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.LOAD_FLATTENED_FIELD.capabilityName()) ); + assumeFalseLogging( + "optional_fields_v3 can't simulate _source loading for unmapped fields in csv tests", + testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.OPTIONAL_FIELDS_V3.capabilityName()) + ); assumeFalseLogging( "can't use rereank in csv tests", testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.RERANK.capabilityName()) From c39104b9171f426d940753b9f53447d95a86342b Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 26 Mar 2026 12:40:20 +0200 Subject: [PATCH 122/137] Add null cases --- .../src/main/resources/unmapped-load.csv-spec | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index 947084926bbcb..2ac4837bf0206 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -554,6 +554,144 @@ partial_mapping_sample_data | 2024-10-23T13:53:55.832Z | Connection er partial_mapping_sample_data | 2024-10-23T13:55:01.543Z | Connected to 10.1.0.1! ; +threeIndicesKeepMessageUnmappedThird +required_capability: optional_fields_v2 +required_capability: source_field_mapping + +SET unmapped_fields="load"\; +FROM partial_mapping_sample_data, sample_data, partial_mapping_no_source_sample_data METADATA _index +| KEEP _index, @timestamp, message +| SORT _index, @timestamp DESC +; + +_index:keyword | @timestamp:date | message:keyword +partial_mapping_no_source_sample_data | 2024-10-23T13:55:01.543Z | null +partial_mapping_no_source_sample_data | 2024-10-23T13:53:55.832Z | null +partial_mapping_no_source_sample_data | 2024-10-23T13:52:55.015Z | null +partial_mapping_no_source_sample_data | 2024-10-23T13:51:54.732Z | null +partial_mapping_no_source_sample_data | 2024-10-23T13:33:34.937Z | null +partial_mapping_no_source_sample_data | 2024-10-23T12:27:28.948Z | null +partial_mapping_no_source_sample_data | 2024-10-23T12:15:03.360Z | null +partial_mapping_sample_data | 2024-10-23T13:55:01.543Z | Connected to 10.1.0.1! +partial_mapping_sample_data | 2024-10-23T13:53:55.832Z | Connection error? +partial_mapping_sample_data | 2024-10-23T13:52:55.015Z | Connection error? +partial_mapping_sample_data | 2024-10-23T13:51:54.732Z | Connection error? +partial_mapping_sample_data | 2024-10-23T13:33:34.937Z | 42 +partial_mapping_sample_data | 2024-10-23T12:27:28.948Z | Connected to 10.1.0.2! +partial_mapping_sample_data | 2024-10-23T12:15:03.360Z | Connected to 10.1.0.3! +sample_data | 2023-10-23T13:55:01.543Z | Connected to 10.1.0.1 +sample_data | 2023-10-23T13:53:55.832Z | Connection error +sample_data | 2023-10-23T13:52:55.015Z | Connection error +sample_data | 2023-10-23T13:51:54.732Z | Connection error +sample_data | 2023-10-23T13:33:34.937Z | Disconnected +sample_data | 2023-10-23T12:27:28.948Z | Connected to 10.1.0.2 +sample_data | 2023-10-23T12:15:03.360Z | Connected to 10.1.0.3 +; + +threeIndicesDropClientIpUnmappedThird +required_capability: optional_fields_v2 +required_capability: source_field_mapping + +SET unmapped_fields="load"\; +FROM partial_mapping_sample_data, sample_data, partial_mapping_no_source_sample_data METADATA _index +| KEEP _index, @timestamp, message, client_ip +| DROP client_ip +| SORT _index, @timestamp DESC +; + +_index:keyword | @timestamp:date | message:keyword +partial_mapping_no_source_sample_data | 2024-10-23T13:55:01.543Z | null +partial_mapping_no_source_sample_data | 2024-10-23T13:53:55.832Z | null +partial_mapping_no_source_sample_data | 2024-10-23T13:52:55.015Z | null +partial_mapping_no_source_sample_data | 2024-10-23T13:51:54.732Z | null +partial_mapping_no_source_sample_data | 2024-10-23T13:33:34.937Z | null +partial_mapping_no_source_sample_data | 2024-10-23T12:27:28.948Z | null +partial_mapping_no_source_sample_data | 2024-10-23T12:15:03.360Z | null +partial_mapping_sample_data | 2024-10-23T13:55:01.543Z | Connected to 10.1.0.1! +partial_mapping_sample_data | 2024-10-23T13:53:55.832Z | Connection error? +partial_mapping_sample_data | 2024-10-23T13:52:55.015Z | Connection error? +partial_mapping_sample_data | 2024-10-23T13:51:54.732Z | Connection error? +partial_mapping_sample_data | 2024-10-23T13:33:34.937Z | 42 +partial_mapping_sample_data | 2024-10-23T12:27:28.948Z | Connected to 10.1.0.2! +partial_mapping_sample_data | 2024-10-23T12:15:03.360Z | Connected to 10.1.0.3! +sample_data | 2023-10-23T13:55:01.543Z | Connected to 10.1.0.1 +sample_data | 2023-10-23T13:53:55.832Z | Connection error +sample_data | 2023-10-23T13:52:55.015Z | Connection error +sample_data | 2023-10-23T13:51:54.732Z | Connection error +sample_data | 2023-10-23T13:33:34.937Z | Disconnected +sample_data | 2023-10-23T12:27:28.948Z | Connected to 10.1.0.2 +sample_data | 2023-10-23T12:15:03.360Z | Connected to 10.1.0.3 +; + +threeIndicesKeepMessageExcludedThird +required_capability: optional_fields_v2 +required_capability: source_field_mapping + +SET unmapped_fields="load"\; +FROM partial_mapping_sample_data, sample_data, partial_mapping_excluded_source_sample_data METADATA _index +| KEEP _index, @timestamp, message +| SORT _index, @timestamp DESC +; + +_index:keyword | @timestamp:date | message:keyword +partial_mapping_excluded_source_sample_data | 2024-10-23T13:55:01.543Z | null +partial_mapping_excluded_source_sample_data | 2024-10-23T13:53:55.832Z | null +partial_mapping_excluded_source_sample_data | 2024-10-23T13:52:55.015Z | null +partial_mapping_excluded_source_sample_data | 2024-10-23T13:51:54.732Z | null +partial_mapping_excluded_source_sample_data | 2024-10-23T13:33:34.937Z | null +partial_mapping_excluded_source_sample_data | 2024-10-23T12:27:28.948Z | null +partial_mapping_excluded_source_sample_data | 2024-10-23T12:15:03.360Z | null +partial_mapping_sample_data | 2024-10-23T13:55:01.543Z | Connected to 10.1.0.1! +partial_mapping_sample_data | 2024-10-23T13:53:55.832Z | Connection error? +partial_mapping_sample_data | 2024-10-23T13:52:55.015Z | Connection error? +partial_mapping_sample_data | 2024-10-23T13:51:54.732Z | Connection error? +partial_mapping_sample_data | 2024-10-23T13:33:34.937Z | 42 +partial_mapping_sample_data | 2024-10-23T12:27:28.948Z | Connected to 10.1.0.2! +partial_mapping_sample_data | 2024-10-23T12:15:03.360Z | Connected to 10.1.0.3! +sample_data | 2023-10-23T13:55:01.543Z | Connected to 10.1.0.1 +sample_data | 2023-10-23T13:53:55.832Z | Connection error +sample_data | 2023-10-23T13:52:55.015Z | Connection error +sample_data | 2023-10-23T13:51:54.732Z | Connection error +sample_data | 2023-10-23T13:33:34.937Z | Disconnected +sample_data | 2023-10-23T12:27:28.948Z | Connected to 10.1.0.2 +sample_data | 2023-10-23T12:15:03.360Z | Connected to 10.1.0.3 +; + +threeIndicesDropClientIpExcludedThird +required_capability: optional_fields_v2 +required_capability: source_field_mapping + +SET unmapped_fields="load"\; +FROM partial_mapping_sample_data, sample_data, partial_mapping_excluded_source_sample_data METADATA _index +| KEEP _index, @timestamp, message, client_ip +| DROP client_ip +| SORT _index, @timestamp DESC +; + +_index:keyword | @timestamp:date | message:keyword +partial_mapping_excluded_source_sample_data | 2024-10-23T13:55:01.543Z | null +partial_mapping_excluded_source_sample_data | 2024-10-23T13:53:55.832Z | null +partial_mapping_excluded_source_sample_data | 2024-10-23T13:52:55.015Z | null +partial_mapping_excluded_source_sample_data | 2024-10-23T13:51:54.732Z | null +partial_mapping_excluded_source_sample_data | 2024-10-23T13:33:34.937Z | null +partial_mapping_excluded_source_sample_data | 2024-10-23T12:27:28.948Z | null +partial_mapping_excluded_source_sample_data | 2024-10-23T12:15:03.360Z | null +partial_mapping_sample_data | 2024-10-23T13:55:01.543Z | Connected to 10.1.0.1! +partial_mapping_sample_data | 2024-10-23T13:53:55.832Z | Connection error? +partial_mapping_sample_data | 2024-10-23T13:52:55.015Z | Connection error? +partial_mapping_sample_data | 2024-10-23T13:51:54.732Z | Connection error? +partial_mapping_sample_data | 2024-10-23T13:33:34.937Z | 42 +partial_mapping_sample_data | 2024-10-23T12:27:28.948Z | Connected to 10.1.0.2! +partial_mapping_sample_data | 2024-10-23T12:15:03.360Z | Connected to 10.1.0.3! +sample_data | 2023-10-23T13:55:01.543Z | Connected to 10.1.0.1 +sample_data | 2023-10-23T13:53:55.832Z | Connection error +sample_data | 2023-10-23T13:52:55.015Z | Connection error +sample_data | 2023-10-23T13:51:54.732Z | Connection error +sample_data | 2023-10-23T13:33:34.937Z | Disconnected +sample_data | 2023-10-23T12:27:28.948Z | Connected to 10.1.0.2 +sample_data | 2023-10-23T12:15:03.360Z | Connected to 10.1.0.3 +; + partialMappingStats required_capability: optional_fields_v3 required_capability: source_field_mapping From 9e3bbcb28921ee5229ae4b24b2fcc9261f8f92bd Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 24 Mar 2026 10:57:51 +0200 Subject: [PATCH 123/137] More CR reviews --- ... esql_potentially_unmapped_expression.csv} | 0 .../resources/transport/upper_bounds/9.4.csv | 2 +- .../xpack/esql/analysis/Analyzer.java | 30 +++++++++---------- .../esql/core/type/MultiTypeEsField.java | 12 +++++--- .../xpack/esql/index/EsIndex.java | 2 +- .../local/ReplaceFieldWithConstantOrNull.java | 9 ++++-- .../planner/EsPhysicalOperationProviders.java | 7 ++--- .../xpack/esql/session/IndexResolver.java | 12 ++++---- .../esql/analysis/AnalyzerTestUtils.java | 4 --- .../esql/analysis/AnalyzerUnmappedTests.java | 26 +++++++--------- .../TestPhysicalOperationProviders.java | 1 - .../esql/type/MultiTypeEsFieldTests.java | 22 +++++++++----- 12 files changed, 65 insertions(+), 62 deletions(-) rename server/src/main/resources/transport/definitions/referable/{esql_unmapped_fields_load.csv => esql_potentially_unmapped_expression.csv} (100%) diff --git a/server/src/main/resources/transport/definitions/referable/esql_unmapped_fields_load.csv b/server/src/main/resources/transport/definitions/referable/esql_potentially_unmapped_expression.csv similarity index 100% rename from server/src/main/resources/transport/definitions/referable/esql_unmapped_fields_load.csv rename to server/src/main/resources/transport/definitions/referable/esql_potentially_unmapped_expression.csv diff --git a/server/src/main/resources/transport/upper_bounds/9.4.csv b/server/src/main/resources/transport/upper_bounds/9.4.csv index 6af1ba42b8e5e..ca2db9065b383 100644 --- a/server/src/main/resources/transport/upper_bounds/9.4.csv +++ b/server/src/main/resources/transport/upper_bounds/9.4.csv @@ -1 +1 @@ -esql_unmapped_fields_load,9325000 +esql_potentially_unmapped_expression,9325000 diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index 1cacb8415db84..f6161d584bbc0 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -1209,7 +1209,7 @@ private Attribute resolveInsistAttribute(Attribute attribute, List ch // TODO: Should the check for partially unmapped fields be done specific to each sub-query in a fork? if (resolvedCol instanceof FieldAttribute fa && indices.stream().anyMatch(r -> r.get().isPartiallyUnmappedField(fa.name()))) { // NOTE: We use indices.getFirst() here as a temporary solution. INSIST will be removed after load is in GA anyway. - return fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa, indices.getFirst()); + return fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa, indices.getFirst().get()); } // Either the field is mapped everywhere and we can just use the resolved column, or the INSIST clause isn't on top of a FROM @@ -1217,8 +1217,8 @@ private Attribute resolveInsistAttribute(Attribute attribute, List ch return resolvedCol; } - private static FieldAttribute invalidInsistAttribute(FieldAttribute fa, IndexResolution indexResolutions) { - InvalidMappedField field = InvalidMappedField.potentiallyUnmapped(fa.name(), getTypesToIndices(fa, indexResolutions.get())); + private static FieldAttribute invalidInsistAttribute(FieldAttribute fa, EsIndex esIndex) { + InvalidMappedField field = InvalidMappedField.potentiallyUnmapped(fa.name(), getTypesToIndices(fa, esIndex)); return new FieldAttribute(fa.source(), null, fa.qualifier(), fa.name(), field); } @@ -1248,14 +1248,6 @@ public static FieldAttribute insistKeyword(Attribute attribute) { */ private static LogicalPlan resolvePartiallyMapped(LogicalPlan plan, AnalyzerContext context) { var indexResolutions = collectIndexResolutions(plan, context); - if (indexResolutions.isEmpty()) { - throw new IllegalStateException("Unmapped fields with empty index resolutions."); - } - if (indexResolutions.size() > 1) { - throw new IllegalStateException( - Strings.format("Multiple index patterns should be disabled with unmapped fields", indexResolutions) - ); - } Map insistedMap = new HashMap<>(); var transformed = plan.transformExpressionsOnly(FieldAttribute.class, fa -> { var esField = fa.field(); @@ -1267,10 +1259,18 @@ private static LogicalPlan resolvePartiallyMapped(LogicalPlan plan, AnalyzerCont if (existing != null) { // field shows up multiple times in the node; return first processing return existing; } - if (indexResolutions.stream().anyMatch(r -> r.get().isPartiallyUnmappedField(fa.name()))) { - FieldAttribute newFA = fa.dataType() == KEYWORD - ? insistKeyword(fa) - : invalidInsistAttribute(fa, indexResolutions.getFirst()); + + if (indexResolutions.isEmpty()) { + throw new IllegalStateException("Unmapped fields with empty index resolutions."); + } + if (indexResolutions.size() > 1) { + throw new IllegalStateException( + Strings.format("Multiple index patterns should be disabled with unmapped fields", indexResolutions) + ); + } + EsIndex esIndex = indexResolutions.getFirst().get(); + if (esIndex.isPartiallyUnmappedField(fa.name())) { + FieldAttribute newFA = fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa, esIndex); insistedMap.put(fa, newFA); return newFA; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java index 242859d38f961..5a42e5ed67e08 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java @@ -32,7 +32,9 @@ * type conversion is done at the data node level. */ public class MultiTypeEsField extends EsField { - private static final TransportVersion UNMAPPED_FIELDS_LOAD = TransportVersion.fromName("esql_unmapped_fields_load"); + private static final TransportVersion POTENTIALLY_UNMAPPED_EXPRESSION = TransportVersion.fromName( + "esql_potentially_unmapped_expression" + ); private final Map indexToConversionExpressions; @@ -63,7 +65,7 @@ protected MultiTypeEsField(StreamInput in) throws IOException { in.readBoolean(), in.readImmutableMap(i -> i.readNamedWriteable(Expression.class)), readTimeSeriesFieldType(in), - in.getTransportVersion().supports(UNMAPPED_FIELDS_LOAD) ? in.readOptionalNamedWriteable(Expression.class) : null + in.getTransportVersion().supports(POTENTIALLY_UNMAPPED_EXPRESSION) ? in.readOptionalNamedWriteable(Expression.class) : null ); } @@ -74,7 +76,9 @@ public void writeContent(StreamOutput out) throws IOException { out.writeBoolean(isAggregatable()); out.writeMap(getIndexToConversionExpressions(), (o, v) -> out.writeNamedWriteable(v)); writeTimeSeriesFieldType(out); - out.writeOptionalNamedWriteable(out.getTransportVersion().supports(UNMAPPED_FIELDS_LOAD) ? potentiallyUnmappedExpression : null); + out.writeOptionalNamedWriteable( + out.getTransportVersion().supports(POTENTIALLY_UNMAPPED_EXPRESSION) ? potentiallyUnmappedExpression : null + ); } public String getWriteableName(TransportVersion transportVersion) { @@ -158,6 +162,6 @@ public int hashCode() { @Override public String toString() { - return Strings.format("%s (%s, %)", super.toString(), indexToConversionExpressions, potentiallyUnmappedExpression); + return Strings.format("%s (%s, %s)", super.toString(), indexToConversionExpressions, potentiallyUnmappedExpression); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/index/EsIndex.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/index/EsIndex.java index 523a5c452530d..351139095cd46 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/index/EsIndex.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/index/EsIndex.java @@ -20,7 +20,7 @@ public record EsIndex( Map indexNameWithModes, Map> originalIndices, // keyed by cluster alias Map> concreteIndices, // keyed by cluster alias - Map> fieldToUnmappedIndices // keyed by field name + Map> fieldToUnmappedIndices // keyed by field name; Set are concrete index names. ) { public EsIndex { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java index 291e530d447e6..5d90deff63d43 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/local/ReplaceFieldWithConstantOrNull.java @@ -87,8 +87,8 @@ else if (esRelation.indexMode() == IndexMode.STANDARD) { // Do not use the attribute name, this can deviate from the field name for union types; use fieldName() instead. // Also retain fields from lookup indices and external sources because we do not have stats for these. Predicate shouldBeRetained = f -> f instanceof TimeSeriesMetadataAttribute - || f.field() instanceof PotentiallyUnmappedKeywordEsField - || (f.field() instanceof MultiTypeEsField mtf && mtf.getPotentiallyUnmappedExpression() != null) + // We should still attempt to load potentially unmapped fields if they're unmapped; that's the whole point! + || isPotentiallyUnmapped(f) // The source (or doc) field is added to the relation output as a hack to enable late materialization in the reduce driver. || EsQueryExec.isDocAttribute(f) || localLogicalOptimizerContext.searchStats().exists(f.fieldName()) @@ -98,6 +98,11 @@ else if (esRelation.indexMode() == IndexMode.STANDARD) { return plan.transformUp(p -> replaceWithNullOrConstant(p, shouldBeRetained, attrToConstant)); } + private static boolean isPotentiallyUnmapped(FieldAttribute f) { + return f.field() instanceof PotentiallyUnmappedKeywordEsField + || (f.field() instanceof MultiTypeEsField mtf && mtf.getPotentiallyUnmappedExpression() != null); + } + private LogicalPlan replaceWithNullOrConstant( LogicalPlan plan, Predicate shouldBeRetained, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java index 24ef97cb45e09..90905d097b33a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java @@ -75,7 +75,6 @@ import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; import org.elasticsearch.xpack.esql.core.expression.FoldContext; -import org.elasticsearch.xpack.esql.core.expression.NamedExpression; import org.elasticsearch.xpack.esql.core.expression.TimeSeriesMetadataAttribute; import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.core.type.FunctionEsField; @@ -216,8 +215,8 @@ public final PhysicalOperation fieldExtractPhysicalOperation( ); } - private static String getFieldName(NamedExpression attr) { - // Do not use the field attribute name, as it can deviate from the field name for union types. + private static String getFieldName(Attribute attr) { + // Do not use the field attribute name, this can deviate from the field name for union types. return attr instanceof FieldAttribute fa ? fa.fieldName().string() : attr.name(); } @@ -265,7 +264,7 @@ private ValuesSourceReaderOperator.LoaderAndConverter blockLoaderAndConverter( if (!(potentiallyUnmapped instanceof AbstractConvertFunction convert)) { return ValuesSourceReaderOperator.LOAD_CONSTANT_NULLS; } - fieldName = getFieldName((NamedExpression) convert.field()); + fieldName = getFieldName((Attribute) convert.field()); shardContext = wrapWithUnmappedFieldContext(shardContext, new PotentiallyUnmappedKeywordEsField(fieldName)); conversion = potentiallyUnmapped; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java index fa6ee2b7d2624..d13a37d7d7efe 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java @@ -299,7 +299,8 @@ public static IndexResolution mergedMappings( OriginalIndexExtractor originalIndexExtractor ) { assert ThreadPool.assertCurrentThreadPool(ThreadPool.Names.SEARCH_COORDINATION); // too expensive to run this on a transport worker - int numberOfIndices = fieldsInfo.caps.getIndexResponses().size(); + List indexResponses = fieldsInfo.caps.getIndexResponses(); + int numberOfIndices = indexResponses.size(); if (numberOfIndices == 0) { return allowEmpty ? IndexResolution.empty(indexPattern) : IndexResolution.notFound(indexPattern); } @@ -309,10 +310,7 @@ public static IndexResolution mergedMappings( Map fieldsCaps = collectedFieldCaps.fieldsCaps; Map indexMappingHashDuplicates = collectedFieldCaps.indexMappingHashDuplicates; Map> fieldToMappedIndices = collectedFieldCaps.fieldToMappedIndices; - Set allIndexNames = fieldsInfo.caps.getIndexResponses() - .stream() - .map(FieldCapabilitiesIndexResponse::getIndexName) - .collect(Collectors.toSet()); + Set allIndexNames = indexResponses.stream().map(FieldCapabilitiesIndexResponse::getIndexName).collect(Collectors.toSet()); // Build hierarchical fields - it's easier to do it in sorted order so the object fields come first. // TODO flattened is simpler - could we get away with that? @@ -364,9 +362,9 @@ public static IndexResolution mergedMappings( } boolean allEmpty = true; - Map indexNameWithModes = Maps.newMapWithExpectedSize(fieldsInfo.caps.getIndexResponses().size()); + Map indexNameWithModes = Maps.newMapWithExpectedSize(indexResponses.size()); Map> concreteIndices = Maps.newHashMapWithExpectedSize(8); - for (FieldCapabilitiesIndexResponse ir : fieldsInfo.caps.getIndexResponses()) { + for (FieldCapabilitiesIndexResponse ir : indexResponses) { allEmpty &= ir.get().isEmpty(); indexNameWithModes.put(ir.getIndexName(), ir.getIndexMode()); var parts = RemoteClusterAware.splitIndexName(ir.getIndexName()); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java index c44a8355c6af1..7e3a52afff752 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java @@ -276,10 +276,6 @@ public static LogicalPlan analyzeStatement(String query, boolean checkPlan) { return analyzeStatement(query, indexResolutions(indexName), checkPlan); } - public static LogicalPlan analyzeStatement(String query, Map indexResolutions) { - return analyzeStatement(query, indexResolutions, true); - } - public static LogicalPlan analyzeStatement(String query, Map indexResolutions, boolean checkPlan) { var statement = TEST_PARSER.createStatement(query); var analyzer = analyzer(indexResolutions, TEST_VERIFIER, configuration(query), statement); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index 9ae3f09560a3b..bc6342902fade 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -546,10 +546,9 @@ public void testTypeConflictLongUnmappedNoCast() { ), List.of() ); - verificationFailure( + typeConflictVerificationFailure( setUnmappedLoad("FROM foo, bar | SORT message"), - indexResolutions(mergedResolution("foo,bar", caps)), - "Cannot use field [message]" + indexResolutions(mergedResolution("foo,bar", caps)) ); } @@ -564,10 +563,9 @@ public void testTypeConflictLongKeywordUnmappedNoCast() { ), List.of() ); - verificationFailure( + typeConflictVerificationFailure( setUnmappedLoad("FROM foo, bar, baz | EVAL x = message + 1"), - indexResolutions(mergedResolution("foo,bar,baz", caps)), - "Cannot use field [message]" + indexResolutions(mergedResolution("foo,bar,baz", caps)) ); } @@ -582,10 +580,9 @@ public void testTypeConflictLongIntUnmappedNoCast() { ), List.of() ); - verificationFailure( + typeConflictVerificationFailure( setUnmappedLoad("FROM foo, bar, baz | SORT message"), - indexResolutions(mergedResolution("foo,bar,baz", caps)), - "Cannot use field [message]" + indexResolutions(mergedResolution("foo,bar,baz", caps)) ); } @@ -599,10 +596,9 @@ public void testTypeConflictTextUnmappedNoCast() { ), List.of() ); - verificationFailure( + typeConflictVerificationFailure( setUnmappedLoad("FROM foo, bar | EVAL x = message"), - indexResolutions(mergedResolution("foo,bar", caps)), - "Cannot use field [message]" + indexResolutions(mergedResolution("foo,bar", caps)) ); } @@ -778,9 +774,9 @@ private void verificationFailure(String statement, String expectedFailure) { assertThat(e.getMessage(), containsString(expectedFailure)); } - private void verificationFailure(String statement, Map indexResolutions, String expectedFailure) { - var e = expectThrows(VerificationException.class, () -> analyzeStatement(statement, indexResolutions)); - assertThat(e.getMessage(), containsString(expectedFailure)); + private void typeConflictVerificationFailure(String statement, Map indexResolutions) { + var e = expectThrows(VerificationException.class, () -> analyzeStatement(statement, indexResolutions, true)); + assertThat(e.getMessage(), containsString("Cannot use field [message]")); } private static String setUnmappedNullify(String query) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java index 504644f0a0727..4cce7aa85e9b7 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/TestPhysicalOperationProviders.java @@ -108,7 +108,6 @@ Optional columnIndex(String columnName) { var result = IntStream.range(0, columnNames.size()).filter(i -> columnNames.get(i).equals(columnName)).findFirst(); return result.isPresent() ? Optional.of(result.getAsInt()) : Optional.empty(); } - } private static AnalysisRegistry createAnalysisRegistry() throws IOException { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/MultiTypeEsFieldTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/MultiTypeEsFieldTests.java index d7d0f93a41f78..e4fe0177c736e 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/MultiTypeEsFieldTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/MultiTypeEsFieldTests.java @@ -64,8 +64,11 @@ protected MultiTypeEsField createTestInstance() { DataType dataType = randomFrom(types()); DataType toType = toString ? DataType.KEYWORD : dataType; Map indexToConvertExpressions = randomConvertExpressions(name, toString, dataType); + Expression potentiallyUnmappedExpression = randomBoolean() ? null : createToString(name, dataType); + EsField.TimeSeriesFieldType tsType = randomFrom(EsField.TimeSeriesFieldType.values()); - return new MultiTypeEsField(name, toType, false, indexToConvertExpressions, tsType, null); + + return new MultiTypeEsField(name, toType, false, indexToConvertExpressions, tsType, potentiallyUnmappedExpression); } @Override @@ -74,14 +77,16 @@ protected MultiTypeEsField mutateInstance(MultiTypeEsField instance) throws IOEx DataType dataType = instance.getDataType(); Map indexToConvertExpressions = instance.getIndexToConversionExpressions(); EsField.TimeSeriesFieldType tsType = instance.getTimeSeriesFieldType(); - switch (between(0, 3)) { + Expression potentiallyUnmappedExpression = instance.getPotentiallyUnmappedExpression(); + switch (between(0, 4)) { case 0 -> name = randomAlphaOfLength(name.length() + 1); case 1 -> dataType = randomValueOtherThan(dataType, () -> randomFrom(DataType.types())); case 2 -> indexToConvertExpressions = mutateConvertExpressions(name, dataType, indexToConvertExpressions); case 3 -> tsType = randomValueOtherThan(tsType, () -> randomFrom(EsField.TimeSeriesFieldType.values())); + case 4 -> potentiallyUnmappedExpression = potentiallyUnmappedExpression != null ? null : createToString(name, dataType); default -> throw new IllegalArgumentException(); } - return new MultiTypeEsField(name, dataType, false, indexToConvertExpressions, tsType, null); + return new MultiTypeEsField(name, dataType, false, indexToConvertExpressions, tsType, potentiallyUnmappedExpression); } @Override @@ -94,11 +99,8 @@ protected final NamedWriteableRegistry getNamedWriteableRegistry() { private Map randomConvertExpressions(String name, boolean toString, DataType dataType) { Map indexToConvertExpressions = new HashMap<>(); if (toString) { - indexToConvertExpressions.put(randomAlphaOfLength(4), new ToString(Source.EMPTY, fieldAttribute(name, dataType), config())); - indexToConvertExpressions.put( - randomAlphaOfLength(4), - new ToString(Source.EMPTY, fieldAttribute(name, DataType.KEYWORD), config()) - ); + indexToConvertExpressions.put(randomAlphaOfLength(4), createToString(name, dataType)); + indexToConvertExpressions.put(randomAlphaOfLength(4), createToString(name, DataType.KEYWORD)); } else { indexToConvertExpressions.put(randomAlphaOfLength(4), testConvertExpression(name, DataType.KEYWORD, dataType)); indexToConvertExpressions.put(randomAlphaOfLength(4), testConvertExpression(name, dataType, dataType)); @@ -157,4 +159,8 @@ private Expression testConvertExpression(String name, DataType fromType, DataTyp private static FieldAttribute fieldAttribute(String name, DataType dataType) { return new FieldAttribute(Source.EMPTY, name, new EsField(name, dataType, Map.of(), true, EsField.TimeSeriesFieldType.NONE)); } + + private ToString createToString(String name, DataType dataType) { + return new ToString(Source.EMPTY, fieldAttribute(name, dataType), config()); + } } From 452338aae73afe02bd538af759ab9eee5afce320 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 24 Mar 2026 15:28:14 +0200 Subject: [PATCH 124/137] Remove FIXME --- .../elasticsearch/xpack/esql/type/InvalidMappedFieldTests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/InvalidMappedFieldTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/InvalidMappedFieldTests.java index e140ef1db8693..fc35e940a8c13 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/InvalidMappedFieldTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/type/InvalidMappedFieldTests.java @@ -12,7 +12,6 @@ import java.util.Map; -// FIXME(gal, NOCOMMIT) Add new boolean property public class InvalidMappedFieldTests extends AbstractEsFieldTypeTests { static InvalidMappedField randomInvalidMappedField(int maxPropertiesDepth) { String name = randomAlphaOfLength(4); From 53f8e43e10ee4b8494e958c1686d0779f15f1068 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 24 Mar 2026 15:28:20 +0200 Subject: [PATCH 125/137] Add tests --- .../unmapped-type-conflicts.csv-spec | 436 +++++++++++++++++- 1 file changed, 425 insertions(+), 11 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec index 98948032dd696..9f1a484eb43d1 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec @@ -345,7 +345,6 @@ heights | null typeConflictLongDateUnmappedCastToKeyword required_capability: optional_fields_v3 -required_capability: index_metadata_field SET unmapped_fields="load"\; FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index @@ -380,7 +379,6 @@ sample_data_ts_long | 1698069301543 typeConflictLongDateUnmappedCastToDouble required_capability: optional_fields_v3 -required_capability: index_metadata_field SET unmapped_fields="load"\; FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index @@ -423,7 +421,6 @@ sample_data_ts_long | 1.698069301543E12 typeConflictLongDateUnmappedCastToDate required_capability: optional_fields_v3 -required_capability: index_metadata_field SET unmapped_fields="load"\; FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index @@ -458,7 +455,6 @@ sample_data_ts_long | 2023-10-23T13:55:01.543Z typeConflictLongDateUnmappedCastToDateNoSort required_capability: optional_fields_v3 -required_capability: index_metadata_field SET unmapped_fields="load"\; FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index @@ -497,7 +493,6 @@ sample_data_ts_long | 2023-10-23T13:55:01.543Z typeConflictLongDateNonExistentCastToKeyword required_capability: optional_fields_v3 -required_capability: index_metadata_field SET unmapped_fields="load"\; FROM sample_data_ts_long, sample_data, colors METADATA _index @@ -537,7 +532,6 @@ colors | null typeConflictLongDateNonExistentCastToDouble required_capability: optional_fields_v3 -required_capability: index_metadata_field SET unmapped_fields="load"\; FROM sample_data_ts_long, sample_data, colors METADATA _index @@ -577,7 +571,6 @@ colors | null typeConflictLongDateNonExistentCastToDate required_capability: optional_fields_v3 -required_capability: index_metadata_field SET unmapped_fields="load"\; FROM sample_data_ts_long, sample_data, colors METADATA _index @@ -621,7 +614,6 @@ colors | null typeConflictLongDateUnmappedNonExistentCastToKeyword required_capability: optional_fields_v3 -required_capability: index_metadata_field SET unmapped_fields="load"\; FROM sample_data_ts_long, sample_data, no_mapping_sample_data, colors METADATA _index @@ -666,7 +658,6 @@ colors | null typeConflictLongDateUnmappedNonExistentCastToDouble required_capability: optional_fields_v3 -required_capability: index_metadata_field SET unmapped_fields="load"\; FROM sample_data_ts_long, sample_data, no_mapping_sample_data, colors METADATA _index @@ -719,7 +710,6 @@ colors | null typeConflictLongDateUnmappedNonExistentCastToDate required_capability: optional_fields_v3 -required_capability: index_metadata_field SET unmapped_fields="load"\; FROM sample_data_ts_long, sample_data, no_mapping_sample_data, colors METADATA _index @@ -764,7 +754,6 @@ colors | null typeConflictLongDateUnmappedNonExistentCastToDateNoSort required_capability: optional_fields_v3 -required_capability: index_metadata_field SET unmapped_fields="load"\; FROM sample_data_ts_long, sample_data, no_mapping_sample_data, heights METADATA _index @@ -801,3 +790,428 @@ sample_data_ts_long | 2023-10-23T13:52:55.015Z sample_data_ts_long | 2023-10-23T13:53:55.832Z sample_data_ts_long | 2023-10-23T13:55:01.543Z ; + +############################## +# WHERE with type casts # +############################## + +typeConflictLongUnmappedWhereWithCastToLong +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| WHERE event_duration::long > 3000000 +| EVAL event_duration = event_duration::keyword +| KEEP _index, event_duration +| SORT _index, event_duration +; + +_index:keyword | event_duration:keyword +no_mapping_sample_data | 3450232 +no_mapping_sample_data | 5033754 +no_mapping_sample_data | 8268152 +sample_data | 3450233 +sample_data | 5033755 +sample_data | 8268153 +; + +noTypeConflictKeywordUnmappedWhereWithCastToKeyword +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| WHERE message::keyword LIKE "Connected*" +| KEEP _index, message +| SORT _index, message +; + +_index:keyword | message:keyword +no_mapping_sample_data | Connected to 10.1.0.1! +no_mapping_sample_data | Connected to 10.1.0.2! +no_mapping_sample_data | Connected to 10.1.0.3! +sample_data | Connected to 10.1.0.1 +sample_data | Connected to 10.1.0.2 +sample_data | Connected to 10.1.0.3 +; + +typeConflictLongNonExistentWhereWithCastToLong +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, colors METADATA _index +| WHERE event_duration::long > 3000000 +| EVAL event_duration = event_duration::keyword +| KEEP _index, event_duration +| SORT _index DESC, event_duration +; + +_index:keyword | event_duration:keyword +sample_data | 3450233 +sample_data | 5033755 +sample_data | 8268153 +; + +typeConflictLongDateUnmappedWhereWithCastToDate +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index +| WHERE @timestamp::date > "2024-01-01T00:00:00.000Z" +| EVAL ts = @timestamp::keyword +| KEEP _index, ts +| SORT _index, ts +; + +_index:keyword | ts:keyword +no_mapping_sample_data | 2024-10-23T12:15:03.360Z +no_mapping_sample_data | 2024-10-23T12:27:28.948Z +no_mapping_sample_data | 2024-10-23T13:33:34.937Z +no_mapping_sample_data | 2024-10-23T13:51:54.732Z +no_mapping_sample_data | 2024-10-23T13:52:55.015Z +no_mapping_sample_data | 2024-10-23T13:53:55.832Z +no_mapping_sample_data | 2024-10-23T13:55:01.543Z +; + +############################# +# SORT with type casts # +############################# + +typeConflictLongUnmappedSortWithCastToLong +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| SORT event_duration::long, _index +| KEEP _index, event_duration +; + +_index:keyword | event_duration:long +no_mapping_sample_data | null +sample_data | 725448 +no_mapping_sample_data | null +sample_data | 1232382 +no_mapping_sample_data | null +sample_data | 1756467 +no_mapping_sample_data | null +sample_data | 2764889 +no_mapping_sample_data | null +sample_data | 3450233 +no_mapping_sample_data | null +sample_data | 5033755 +no_mapping_sample_data | null +sample_data | 8268153 +; + +typeConflictLongUnmappedSortWithCastToKeyword +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| SORT event_duration::keyword, _index +| KEEP _index, event_duration +; + +_index:keyword | event_duration:long +no_mapping_sample_data | null +sample_data | 1232382 +no_mapping_sample_data | null +sample_data | 1756467 +no_mapping_sample_data | null +sample_data | 2764889 +no_mapping_sample_data | null +sample_data | 3450233 +no_mapping_sample_data | null +sample_data | 5033755 +no_mapping_sample_data | null +sample_data | 725448 +no_mapping_sample_data | null +sample_data | 8268153 +; + +############################ +# Chained type casts # +############################ + +typeConflictLongUnmappedChainedCastLongToKeyword +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL event_duration = event_duration::long::keyword +| KEEP _index, event_duration +| SORT _index, event_duration +; + +_index:keyword | event_duration:keyword +no_mapping_sample_data | 1232381 +no_mapping_sample_data | 1756466 +no_mapping_sample_data | 2764888 +no_mapping_sample_data | 3450232 +no_mapping_sample_data | 5033754 +no_mapping_sample_data | 725447 +no_mapping_sample_data | 8268152 +sample_data | 1232382 +sample_data | 1756467 +sample_data | 2764889 +sample_data | 3450233 +sample_data | 5033755 +sample_data | 725448 +sample_data | 8268153 +; + +typeConflictLongUnmappedChainedCastLongToDouble +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| EVAL event_duration = event_duration::long::double +| KEEP _index, event_duration +| SORT _index, event_duration +; + +_index:keyword | event_duration:double +no_mapping_sample_data | 725447.0 +no_mapping_sample_data | 1232381.0 +no_mapping_sample_data | 1756466.0 +no_mapping_sample_data | 2764888.0 +no_mapping_sample_data | 3450232.0 +no_mapping_sample_data | 5033754.0 +no_mapping_sample_data | 8268152.0 +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +; + +typeConflictLongDateUnmappedChainedCastDateToKeyword +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data_ts_long, sample_data, no_mapping_sample_data METADATA _index +| EVAL ts = @timestamp::date::keyword +| KEEP _index, ts +| SORT _index, ts +; + +_index:keyword | ts:keyword +no_mapping_sample_data | 2024-10-23T12:15:03.360Z +no_mapping_sample_data | 2024-10-23T12:27:28.948Z +no_mapping_sample_data | 2024-10-23T13:33:34.937Z +no_mapping_sample_data | 2024-10-23T13:51:54.732Z +no_mapping_sample_data | 2024-10-23T13:52:55.015Z +no_mapping_sample_data | 2024-10-23T13:53:55.832Z +no_mapping_sample_data | 2024-10-23T13:55:01.543Z +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +sample_data_ts_long | 2023-10-23T12:15:03.360Z +sample_data_ts_long | 2023-10-23T12:27:28.948Z +sample_data_ts_long | 2023-10-23T13:33:34.937Z +sample_data_ts_long | 2023-10-23T13:51:54.732Z +sample_data_ts_long | 2023-10-23T13:52:55.015Z +sample_data_ts_long | 2023-10-23T13:53:55.832Z +sample_data_ts_long | 2023-10-23T13:55:01.543Z +; + +typeConflictLongUnmappedChainedCastInWhere +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, no_mapping_sample_data METADATA _index +| WHERE event_duration::long::double > 3000000.0 +| EVAL event_duration = event_duration::keyword +| KEEP _index, event_duration +| SORT _index, event_duration +; + +_index:keyword | event_duration:keyword +no_mapping_sample_data | 3450232 +no_mapping_sample_data | 5033754 +no_mapping_sample_data | 8268152 +sample_data | 3450233 +sample_data | 5033755 +sample_data | 8268153 +; + +#################################### +# Mapped and _source excluded # +#################################### + +noTypeConflictKeywordSourceExcludedNoCast +required_capability: optional_fields_v3 +required_capability: source_field_mapping + +SET unmapped_fields="load"\; +FROM sample_data, partial_mapping_no_source_sample_data METADATA _index +| KEEP _index, message +| SORT _index DESC, message +| LIMIT 15 +; + +_index:keyword | message:keyword +sample_data | Connected to 10.1.0.1 +sample_data | Connected to 10.1.0.2 +sample_data | Connected to 10.1.0.3 +sample_data | Connection error +sample_data | Connection error +sample_data | Connection error +sample_data | Disconnected +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +; + +noTypeConflictKeywordSourceExcludedCastToKeyword +required_capability: optional_fields_v3 +required_capability: source_field_mapping + +SET unmapped_fields="load"\; +FROM sample_data, partial_mapping_no_source_sample_data METADATA _index +| EVAL message = message::keyword +| KEEP _index, message +| SORT _index DESC, message +| LIMIT 15 +; + +_index:keyword | message:keyword +sample_data | Connected to 10.1.0.1 +sample_data | Connected to 10.1.0.2 +sample_data | Connected to 10.1.0.3 +sample_data | Connection error +sample_data | Connection error +sample_data | Connection error +sample_data | Disconnected +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +; + +typeConflictLongSourceExcludedCastToKeyword +required_capability: optional_fields_v3 +required_capability: source_field_mapping + +SET unmapped_fields="load"\; +FROM sample_data, partial_mapping_no_source_sample_data METADATA _index +| EVAL event_duration = event_duration::keyword +| KEEP _index, event_duration +| SORT _index DESC, event_duration +| LIMIT 15 +; + +_index:keyword | event_duration:keyword +sample_data | 1232382 +sample_data | 1756467 +sample_data | 2764889 +sample_data | 3450233 +sample_data | 5033755 +sample_data | 725448 +sample_data | 8268153 +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +; + +typeConflictLongSourceExcludedCastToLong +required_capability: optional_fields_v3 +required_capability: source_field_mapping + +SET unmapped_fields="load"\; +FROM sample_data, partial_mapping_no_source_sample_data METADATA _index +| EVAL event_duration = event_duration::long +| KEEP _index, event_duration +| SORT _index DESC, event_duration +| LIMIT 15 +; + +_index:keyword | event_duration:long +sample_data | 725448 +sample_data | 1232382 +sample_data | 1756467 +sample_data | 2764889 +sample_data | 3450233 +sample_data | 5033755 +sample_data | 8268153 +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +; + +typeConflictLongSourceExcludedCastToDouble +required_capability: optional_fields_v3 +required_capability: source_field_mapping + +SET unmapped_fields="load"\; +FROM sample_data, partial_mapping_no_source_sample_data METADATA _index +| EVAL event_duration = event_duration::double +| KEEP _index, event_duration +| SORT _index DESC, event_duration +| LIMIT 15 +; + +_index:keyword | event_duration:double +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +; + +typeConflictLongSourceExcludedCastToDoubleNoSort +required_capability: optional_fields_v3 +required_capability: source_field_mapping + +SET unmapped_fields="load"\; +FROM sample_data, partial_mapping_no_source_sample_data METADATA _index +| EVAL event_duration = event_duration::double +| KEEP _index, event_duration +; +ignoreOrder:true + +_index:keyword | event_duration:double +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +partial_mapping_no_source_sample_data | null +sample_data | 725448.0 +sample_data | 1232382.0 +sample_data | 1756467.0 +sample_data | 2764889.0 +sample_data | 3450233.0 +sample_data | 5033755.0 +sample_data | 8268153.0 +; From f789d7acdf56fe3024ad485ee1db007854fc692b Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 24 Mar 2026 15:36:27 +0200 Subject: [PATCH 126/137] Add golden test coverage --- .../analysis/AnalyzerUnmappedGoldenTests.java | 24 +++++++++++++++++++ .../load/analysis.expected | 4 ++++ .../load/query.esql | 3 +++ .../nullify/analysis.expected | 4 ++++ .../nullify/query.esql | 3 +++ .../load/analysis.expected | 4 ++++ .../load/query.esql | 3 +++ .../nullify/analysis.expected | 4 ++++ .../nullify/query.esql | 3 +++ .../load/analysis.expected | 4 ++++ .../load/query.esql | 3 +++ .../nullify/analysis.expected | 4 ++++ .../nullify/query.esql | 3 +++ 13 files changed, 66 insertions(+) create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/nullify/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/load/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/load/query.esql create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/nullify/analysis.expected create mode 100644 x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/nullify/query.esql diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java index 1850bcefc88a3..a6db44ab182de 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedGoldenTests.java @@ -651,6 +651,30 @@ public void testMappedToNonKeywordInOneIndexOnly() throws Exception { """); } + public void testTypeConflictMappedAndUnmappedWithCast() throws Exception { + runTests(""" + FROM sample_data, no_mapping_sample_data + | EVAL event_duration = event_duration::long + | KEEP event_duration + """); + } + + public void testTypeConflictMappedTimesTwoAndUnmapped() throws Exception { + runTests(""" + FROM sample_data_ts_long, sample_data, no_mapping_sample_data + | EVAL ts = @timestamp::date + | KEEP ts + """); + } + + public void testNoTypeConflictKeywordAndUnmappedWhere() throws Exception { + runTests(""" + FROM sample_data, no_mapping_sample_data + | WHERE message::keyword LIKE "Connected*" + | KEEP message + """); + } + public void testForkBranchesAfterStats1stBranch() throws Exception { runTestsNullifyOnly(""" FROM employees diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/load/analysis.expected new file mode 100644 index 0000000000000..1de4ceb4f12be --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[message{f(PotentiallyUnmappedKeywordEsField)}#0]] + \_Filter[LIKE(TOSTRING(message{f(PotentiallyUnmappedKeywordEsField)}#0), "Connected*", false)] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#1, client_ip{f}#2, event_duration{f}#3, message{f(PotentiallyUnmappedKeywordEsField)}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/load/query.esql new file mode 100644 index 0000000000000..f101e34ada0eb --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM sample_data, no_mapping_sample_data +| WHERE message::keyword LIKE "Connected*" +| KEEP message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/nullify/analysis.expected new file mode 100644 index 0000000000000..7a3a5b952a724 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[message{f}#0]] + \_Filter[LIKE(TOSTRING(message{f}#0), "Connected*", false)] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#1, client_ip{f}#2, event_duration{f}#3, message{f}#0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/nullify/query.esql new file mode 100644 index 0000000000000..05a5e51d2255b --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testNoTypeConflictKeywordAndUnmappedWhere/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM sample_data, no_mapping_sample_data +| WHERE message::keyword LIKE "Connected*" +| KEEP message diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/load/analysis.expected new file mode 100644 index 0000000000000..fba946502a112 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[event_duration{r}#0]] + \_Eval[[$$event_duration$converted_to$long{f(MultiTypeEsField)$}#1 AS event_duration#0]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#4, message{f}#5, $$event_duration$converted_to$long{f(MultiTypeEsField)$}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/load/query.esql new file mode 100644 index 0000000000000..b8c78ed145ba9 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM sample_data, no_mapping_sample_data +| EVAL event_duration = event_duration::long +| KEEP event_duration diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/nullify/analysis.expected new file mode 100644 index 0000000000000..a58bbac2e73d4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[event_duration{r}#0]] + \_Eval[[TOLONG(event_duration{f}#1) AS event_duration#0]] + \_EsRelation[sample_data,no_mapping_sample_data][@timestamp{f}#2, client_ip{f}#3, event_duration{f}#1, message{f}#4] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/nullify/query.esql new file mode 100644 index 0000000000000..81beb6a23a976 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedAndUnmappedWithCast/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM sample_data, no_mapping_sample_data +| EVAL event_duration = event_duration::long +| KEEP event_duration diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/load/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/load/analysis.expected new file mode 100644 index 0000000000000..4160e1709b996 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/load/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[ts{r}#0]] + \_Eval[[$$@timestamp$converted_to$datetime{f(MultiTypeEsField)$}#1 AS ts#0]] + \_EsRelation[sample_data_ts_long,sample_data,no_mapping_sample_data][!@timestamp, client_ip{f}#2, event_duration{f}#3, message{f}#4, $$@timestamp$converted_to$datetime{f(MultiTypeEsField)$}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/load/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/load/query.esql new file mode 100644 index 0000000000000..7d2c51e708ad1 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/load/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="load"; FROM sample_data_ts_long, sample_data, no_mapping_sample_data +| EVAL ts = @timestamp::date +| KEEP ts diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/nullify/analysis.expected b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/nullify/analysis.expected new file mode 100644 index 0000000000000..4160e1709b996 --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/nullify/analysis.expected @@ -0,0 +1,4 @@ +Limit[1000[INTEGER],false,false] +\_Project[[ts{r}#0]] + \_Eval[[$$@timestamp$converted_to$datetime{f(MultiTypeEsField)$}#1 AS ts#0]] + \_EsRelation[sample_data_ts_long,sample_data,no_mapping_sample_data][!@timestamp, client_ip{f}#2, event_duration{f}#3, message{f}#4, $$@timestamp$converted_to$datetime{f(MultiTypeEsField)$}#1] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/nullify/query.esql b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/nullify/query.esql new file mode 100644 index 0000000000000..f9a3756c3bb8e --- /dev/null +++ b/x-pack/plugin/esql/src/test/resources/org/elasticsearch/xpack/esql/analysis/golden_tests/AnalyzerUnmappedGoldenTests/testTypeConflictMappedTimesTwoAndUnmapped/nullify/query.esql @@ -0,0 +1,3 @@ +SET unmapped_fields="nullify"; FROM sample_data_ts_long, sample_data, no_mapping_sample_data +| EVAL ts = @timestamp::date +| KEEP ts From 6a4566436ab84260722411556a2af4c95144b901 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Tue, 24 Mar 2026 18:43:34 +0200 Subject: [PATCH 127/137] More tests --- .../unmapped-type-conflicts.csv-spec | 51 +++++++++++++++++++ .../esql/analysis/AnalyzerUnmappedTests.java | 41 +++++++++------ 2 files changed, 76 insertions(+), 16 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec index 9f1a484eb43d1..897b3bb2935fc 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec @@ -1215,3 +1215,54 @@ sample_data | 3450233.0 sample_data | 5033755.0 sample_data | 8268153.0 ; + +############################################### +# Date + date_nanos + unmapped (bug repro) # +############################################### + +typeConflictDateNanosDateUnmappedCastToDate +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, sample_data_ts_nanos, no_mapping_sample_data METADATA _index +| EVAL ts = @timestamp::date +| KEEP _index, ts +| SORT _index, ts +; + +_index:keyword | ts:date +no_mapping_sample_data | 2024-10-23T12:15:03.360Z +no_mapping_sample_data | 2024-10-23T12:27:28.948Z +no_mapping_sample_data | 2024-10-23T13:33:34.937Z +no_mapping_sample_data | 2024-10-23T13:51:54.732Z +no_mapping_sample_data | 2024-10-23T13:52:55.015Z +no_mapping_sample_data | 2024-10-23T13:53:55.832Z +no_mapping_sample_data | 2024-10-23T13:55:01.543Z +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +sample_data_ts_nanos | 2023-10-23T12:15:03.360Z +sample_data_ts_nanos | 2023-10-23T12:27:28.948Z +sample_data_ts_nanos | 2023-10-23T13:33:34.937Z +sample_data_ts_nanos | 2023-10-23T13:51:54.732Z +sample_data_ts_nanos | 2023-10-23T13:52:55.015Z +sample_data_ts_nanos | 2023-10-23T13:53:55.832Z +sample_data_ts_nanos | 2023-10-23T13:55:01.543Z +; + +typeConflictDateNanosDateTwoIndexCastToLong +required_capability: union_types + +FROM sample_data, sample_data_ts_nanos METADATA _index +| EVAL ts = @timestamp::long +| KEEP _index, ts +| SORT _index, ts +; + +_index:keyword | ts:long +sample_data | 0 +; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index bc6342902fade..c180381cd0b70 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -51,6 +51,15 @@ // @TestLogging(value = "org.elasticsearch.xpack.esql:TRACE", reason = "debug") public class AnalyzerUnmappedTests extends ESTestCase { + + /** + * Query suffixes that use the unsupported type-conflict field [message] in different commands. + * Each type conflict test iterates over these to verify the error is raised regardless of how the field is used. + */ + private static final String[] TYPE_CONFLICT_QUERY_SUFFIXES = new String[] { + "| SORT message", + "| EVAL x = message", + "| WHERE message IS NOT NULL" }; public void testFailKeepAndNonMatchingStar() { var query = """ FROM test @@ -546,10 +555,10 @@ public void testTypeConflictLongUnmappedNoCast() { ), List.of() ); - typeConflictVerificationFailure( - setUnmappedLoad("FROM foo, bar | SORT message"), - indexResolutions(mergedResolution("foo,bar", caps)) - ); + var resolutions = indexResolutions(mergedResolution("foo,bar", caps)); + for (String suffix : TYPE_CONFLICT_QUERY_SUFFIXES) { + typeConflictVerificationFailure(setUnmappedLoad("FROM foo, bar " + suffix), resolutions); + } } public void testTypeConflictLongKeywordUnmappedNoCast() { @@ -563,10 +572,10 @@ public void testTypeConflictLongKeywordUnmappedNoCast() { ), List.of() ); - typeConflictVerificationFailure( - setUnmappedLoad("FROM foo, bar, baz | EVAL x = message + 1"), - indexResolutions(mergedResolution("foo,bar,baz", caps)) - ); + var resolutions = indexResolutions(mergedResolution("foo,bar,baz", caps)); + for (String suffix : TYPE_CONFLICT_QUERY_SUFFIXES) { + typeConflictVerificationFailure(setUnmappedLoad("FROM foo, bar, baz " + suffix), resolutions); + } } public void testTypeConflictLongIntUnmappedNoCast() { @@ -580,10 +589,10 @@ public void testTypeConflictLongIntUnmappedNoCast() { ), List.of() ); - typeConflictVerificationFailure( - setUnmappedLoad("FROM foo, bar, baz | SORT message"), - indexResolutions(mergedResolution("foo,bar,baz", caps)) - ); + var resolutions = indexResolutions(mergedResolution("foo,bar,baz", caps)); + for (String suffix : TYPE_CONFLICT_QUERY_SUFFIXES) { + typeConflictVerificationFailure(setUnmappedLoad("FROM foo, bar, baz " + suffix), resolutions); + } } public void testTypeConflictTextUnmappedNoCast() { @@ -596,10 +605,10 @@ public void testTypeConflictTextUnmappedNoCast() { ), List.of() ); - typeConflictVerificationFailure( - setUnmappedLoad("FROM foo, bar | EVAL x = message"), - indexResolutions(mergedResolution("foo,bar", caps)) - ); + var resolutions = indexResolutions(mergedResolution("foo,bar", caps)); + for (String suffix : TYPE_CONFLICT_QUERY_SUFFIXES) { + typeConflictVerificationFailure(setUnmappedLoad("FROM foo, bar " + suffix), resolutions); + } } private static final String UNMAPPED_TIMESTAMP_SUFFIX = UnresolvedTimestamp.UNRESOLVED_SUFFIX + Verifier.UNMAPPED_TIMESTAMP_SUFFIX; From fae0da20aac325f5e4f20ea89ce1ebfdfd9c0cf9 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Wed, 25 Mar 2026 12:27:43 +0200 Subject: [PATCH 128/137] Add assertion --- .../elasticsearch/xpack/esql/analysis/Analyzer.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index f6161d584bbc0..35096f38e57e3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -2481,13 +2481,19 @@ private Expression resolveConvertFunction(ConvertFunction convert, List typeResolutions = new HashMap<>(); var convert = new ToDateNanos(f.source(), f, context.configuration()); imf.types().forEach(type -> typeResolutions(f, convert, type, imf, typeResolutions)); + // This rule runs in the "Initialize" batch, before ResolveUnmapped, so isPotentiallyUnmapped() is always false. + if (imf.isPotentiallyUnmapped()) { + throw new IllegalStateException("Unexpected potentially unmapped field [" + imf.getName() + "]"); + } var resolvedField = ResolveUnionTypes.resolvedMultiTypeEsField(f, typeResolutions, null); return new FieldAttribute( f.source(), From cfee60d99a786c80bfcd8a5593c21de62e32ebc8 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 26 Mar 2026 13:07:58 +0200 Subject: [PATCH 129/137] Fix nanos bug --- .../unmapped-type-conflicts.csv-spec | 85 ++++++++----------- .../xpack/esql/analysis/Analyzer.java | 23 ++++- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec index 897b3bb2935fc..3483e07d168cc 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-type-conflicts.csv-spec @@ -339,6 +339,40 @@ heights | null heights | null ; +typeConflictDateNanosDateUnmappedCastToDate +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, sample_data_ts_nanos, no_mapping_sample_data METADATA _index +| EVAL ts = @timestamp::date +| KEEP _index, ts +| SORT _index, ts +; + +_index:keyword | ts:datetime +no_mapping_sample_data | 2024-10-23T12:15:03.360Z +no_mapping_sample_data | 2024-10-23T12:27:28.948Z +no_mapping_sample_data | 2024-10-23T13:33:34.937Z +no_mapping_sample_data | 2024-10-23T13:51:54.732Z +no_mapping_sample_data | 2024-10-23T13:52:55.015Z +no_mapping_sample_data | 2024-10-23T13:53:55.832Z +no_mapping_sample_data | 2024-10-23T13:55:01.543Z +sample_data | 2023-10-23T12:15:03.360Z +sample_data | 2023-10-23T12:27:28.948Z +sample_data | 2023-10-23T13:33:34.937Z +sample_data | 2023-10-23T13:51:54.732Z +sample_data | 2023-10-23T13:52:55.015Z +sample_data | 2023-10-23T13:53:55.832Z +sample_data | 2023-10-23T13:55:01.543Z +sample_data_ts_nanos | 2023-10-23T12:15:03.360Z +sample_data_ts_nanos | 2023-10-23T12:27:28.948Z +sample_data_ts_nanos | 2023-10-23T13:33:34.937Z +sample_data_ts_nanos | 2023-10-23T13:51:54.732Z +sample_data_ts_nanos | 2023-10-23T13:52:55.015Z +sample_data_ts_nanos | 2023-10-23T13:53:55.832Z +sample_data_ts_nanos | 2023-10-23T13:55:01.543Z +; + ########################### # Mapped x 2 and unmapped # ########################### @@ -1215,54 +1249,3 @@ sample_data | 3450233.0 sample_data | 5033755.0 sample_data | 8268153.0 ; - -############################################### -# Date + date_nanos + unmapped (bug repro) # -############################################### - -typeConflictDateNanosDateUnmappedCastToDate -required_capability: optional_fields_v3 - -SET unmapped_fields="load"\; -FROM sample_data, sample_data_ts_nanos, no_mapping_sample_data METADATA _index -| EVAL ts = @timestamp::date -| KEEP _index, ts -| SORT _index, ts -; - -_index:keyword | ts:date -no_mapping_sample_data | 2024-10-23T12:15:03.360Z -no_mapping_sample_data | 2024-10-23T12:27:28.948Z -no_mapping_sample_data | 2024-10-23T13:33:34.937Z -no_mapping_sample_data | 2024-10-23T13:51:54.732Z -no_mapping_sample_data | 2024-10-23T13:52:55.015Z -no_mapping_sample_data | 2024-10-23T13:53:55.832Z -no_mapping_sample_data | 2024-10-23T13:55:01.543Z -sample_data | 2023-10-23T12:15:03.360Z -sample_data | 2023-10-23T12:27:28.948Z -sample_data | 2023-10-23T13:33:34.937Z -sample_data | 2023-10-23T13:51:54.732Z -sample_data | 2023-10-23T13:52:55.015Z -sample_data | 2023-10-23T13:53:55.832Z -sample_data | 2023-10-23T13:55:01.543Z -sample_data_ts_nanos | 2023-10-23T12:15:03.360Z -sample_data_ts_nanos | 2023-10-23T12:27:28.948Z -sample_data_ts_nanos | 2023-10-23T13:33:34.937Z -sample_data_ts_nanos | 2023-10-23T13:51:54.732Z -sample_data_ts_nanos | 2023-10-23T13:52:55.015Z -sample_data_ts_nanos | 2023-10-23T13:53:55.832Z -sample_data_ts_nanos | 2023-10-23T13:55:01.543Z -; - -typeConflictDateNanosDateTwoIndexCastToLong -required_capability: union_types - -FROM sample_data, sample_data_ts_nanos METADATA _index -| EVAL ts = @timestamp::long -| KEEP _index, ts -| SORT _index, ts -; - -_index:keyword | ts:long -sample_data | 0 -; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index 35096f38e57e3..92c22ee296a0d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -2655,13 +2655,16 @@ public LogicalPlan apply(LogicalPlan plan, AnalyzerContext context) { return relation; } return relation.transformExpressionsUp(FieldAttribute.class, f -> { - if (f.field() instanceof InvalidMappedField imf && imf.types().stream().allMatch(DataType::isDate)) { + if (f.field() instanceof InvalidMappedField imf && allDates(context, relation, imf)) { HashMap typeResolutions = new HashMap<>(); var convert = new ToDateNanos(f.source(), f, context.configuration()); imf.types().forEach(type -> typeResolutions(f, convert, type, imf, typeResolutions)); - // This rule runs in the "Initialize" batch, before ResolveUnmapped, so isPotentiallyUnmapped() is always false. + // This rule runs in the "Initialize" batch, before ResolveUnmapped. The isFieldMappedInAllIndices + // check above should prevent reaching here for fields that are unmapped in any index when in LOAD mode. if (imf.isPotentiallyUnmapped()) { - throw new IllegalStateException("Unexpected potentially unmapped field [" + imf.getName() + "]"); + throw new IllegalStateException( + "Unexpected potentially unmapped field [" + imf.getName() + "] in DateMillisToNanosInEsRelation" + ); } var resolvedField = ResolveUnionTypes.resolvedMultiTypeEsField(f, typeResolutions, null); return new FieldAttribute( @@ -2679,6 +2682,20 @@ public LogicalPlan apply(LogicalPlan plan, AnalyzerContext context) { }); }); } + + private static boolean allDates(AnalyzerContext context, EsRelation relation, InvalidMappedField imf) { + if (imf.types().stream().allMatch(DataType::isDate) == false) { + return false; + } + // If we need to load the fields from unmapped indices, we will treat it as a keyword, i.e., not all types are dates. + if (context.unmappedResolution() != UnmappedResolution.LOAD) { + return true; + } + // Since DateMillisToNanosInEsRelation runs before ResolveUnmapped, isPotentiallyUnmapped isn't set yet. + int mappedCount = imf.getTypesToIndices().values().stream().mapToInt(Set::size).sum(); + int totalCount = relation.concreteIndices().values().stream().mapToInt(List::size).sum(); + return mappedCount >= totalCount; + } } private static void typeResolutions( From 18bf717fe527cad07d3880ef921f46ad5bcc5e79 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Thu, 26 Mar 2026 11:28:49 +0000 Subject: [PATCH 130/137] [CI] Auto commit changes from spotless --- .../elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index c180381cd0b70..d73dec4df7074 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -60,6 +60,7 @@ public class AnalyzerUnmappedTests extends ESTestCase { "| SORT message", "| EVAL x = message", "| WHERE message IS NOT NULL" }; + public void testFailKeepAndNonMatchingStar() { var query = """ FROM test From dc33f9126a071736518a015c4826cf410201e6c5 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 26 Mar 2026 15:48:56 +0200 Subject: [PATCH 131/137] Bump optional_fields to v3 --- .../src/main/resources/unmapped-load.csv-spec | 8 ++++---- .../testFixtures/src/main/resources/views.csv-spec | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index 2ac4837bf0206..92022c177e203 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -555,7 +555,7 @@ partial_mapping_sample_data | 2024-10-23T13:55:01.543Z | Connected to ; threeIndicesKeepMessageUnmappedThird -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: source_field_mapping SET unmapped_fields="load"\; @@ -589,7 +589,7 @@ sample_data | 2023-10-23T12:15:03.360Z | Connected to ; threeIndicesDropClientIpUnmappedThird -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: source_field_mapping SET unmapped_fields="load"\; @@ -624,7 +624,7 @@ sample_data | 2023-10-23T12:15:03.360Z | Connected to ; threeIndicesKeepMessageExcludedThird -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: source_field_mapping SET unmapped_fields="load"\; @@ -658,7 +658,7 @@ sample_data | 2023-10-23T12:15:03.360Z | Connect ; threeIndicesDropClientIpExcludedThird -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: source_field_mapping SET unmapped_fields="load"\; diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/views.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/views.csv-spec index 2f512bff2c3f1..113e072271b0f 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/views.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/views.csv-spec @@ -459,7 +459,7 @@ total:long | country:keyword ; unmappedFields_Load_with_Count -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: views_with_branching required_capability: views_crud_as_index_actions @@ -475,7 +475,7 @@ rehired_count:long ; unmappedFields_Load_with_WithNonExistentField -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: views_with_branching required_capability: views_crud_as_index_actions @@ -491,7 +491,7 @@ rehired_count:long | null_count:long ; unmappedFields_Load_with_EvalOnNonExistentField -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: views_with_branching required_capability: views_crud_as_index_actions @@ -509,7 +509,7 @@ c:long ; unmappedFields_Load_with_WhereOnNonExistentField -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: views_with_branching required_capability: views_crud_as_index_actions @@ -526,7 +526,7 @@ c:long ; unmappedFields_Load_with_StatsByNonExistentField -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: views_with_branching required_capability: views_crud_as_index_actions @@ -542,7 +542,7 @@ c:long | nonexistent_field:keyword ; unmappedFields_Load_with_SortByNonExistentField -required_capability: optional_fields_v2 +required_capability: optional_fields_v3 required_capability: views_with_branching required_capability: views_crud_as_index_actions From b6c29563f13630736fa3000d2d7e6a6584f20cbb Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 26 Mar 2026 16:08:00 +0200 Subject: [PATCH 132/137] Fix wrong counting when two indices have the same mapping --- .../xpack/esql/session/IndexResolver.java | 19 +++++---- .../xpack/esql/analysis/AnalyzerTests.java | 42 ------------------- .../esql/analysis/AnalyzerUnmappedTests.java | 23 ++++++++++ 3 files changed, 34 insertions(+), 50 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java index d13a37d7d7efe..7cc8807bfc487 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java @@ -408,20 +408,23 @@ private static CollectedFieldCaps collectFieldCaps(FieldCapabilitiesResponse fie Map> fieldToMappedIndices = new HashMap<>(); for (FieldCapabilitiesIndexResponse response : fieldCapsResponse.getIndexResponses()) { - if (indexMappingHashToDuplicateCount.compute(response.getIndexMappingHash(), (k, v) -> v == null ? 1 : v + 1) > 1) { - continue; - } + boolean isNew = indexMappingHashToDuplicateCount.compute( + response.getIndexMappingHash(), + (k, v) -> v == null ? 1 : v + 1 + ) <= 1; String indexName = response.getIndexName(); for (IndexFieldCapabilities fc : response.get().values()) { if (fc.isMetadatafield()) { // ESQL builds the metadata fields if they are asked for without using the resolution. continue; } - List all = fieldsCaps.computeIfAbsent( - fc.name(), - (_key) -> new IndexFieldCapabilitiesWithSourceHash(new ArrayList<>(), response.getIndexMappingHash()) - ).fieldCapabilities; - all.add(fc); + if (isNew) { + List all = fieldsCaps.computeIfAbsent( + fc.name(), + (_key) -> new IndexFieldCapabilitiesWithSourceHash(new ArrayList<>(), response.getIndexMappingHash()) + ).fieldCapabilities; + all.add(fc); + } fieldToMappedIndices.computeIfAbsent(fc.name(), k -> new HashSet<>()).add(indexName); } } 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 8409258e9e8d5..14bbeeafb0f33 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 @@ -3405,25 +3405,6 @@ public void testResolveInsist_multiIndexFieldPartiallyExistsWithMultiTypesNoKeyw assertThat(attr.unresolvedMessage(), is(expected)); } - public void testResolveInsist_multiIndexSameMapping_fieldIsMapped() { - assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); - - FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( - List.of( - fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "long")), - fieldCapabilitiesIndexResponse("bar", fieldResponseMap("message", "long")) - ), - List.of() - ); - IndexResolution resolution = mergedResolution("foo,bar", caps); - var plan = analyzer().addIndex(resolution).query("FROM foo, bar | INSIST_🐔 message"); - var limit = as(plan, Limit.class); - var insist = as(limit.child(), Insist.class); - var attribute = (FieldAttribute) EsqlTestUtils.singleValue(insist.output()); - assertThat(attribute.name(), is("message")); - assertThat(attribute.dataType(), is(DataType.LONG)); - } - public void testResolveInsist_multiIndexFieldPartiallyExistsWithMultiTypesWithKeyword_createsAnInvalidMappedField() { assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); @@ -3447,29 +3428,6 @@ public void testResolveInsist_multiIndexFieldPartiallyExistsWithMultiTypesWithKe assertThat(attr.unresolvedMessage(), is(expected)); } - public void testResolveInsist_multiIndexFieldPartiallyExistsWithMultiTypesWithCast_castsAreNotSupported() { - assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); - - FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( - List.of( - fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "long")), - fieldCapabilitiesIndexResponse("bar", fieldResponseMap("message", "date")), - fieldCapabilitiesIndexResponse("bazz", Map.of()) - ), - List.of() - ); - IndexResolution resolution = mergedResolution("foo,bar", caps); - VerificationException e = expectThrows( - VerificationException.class, - () -> analyzer().addIndex(resolution).query("FROM foo, bar | INSIST_🐔 message | EVAL message = message :: keyword") - ); - // This isn't the most informative error, but it'll do for now. - assertThat( - e.getMessage(), - containsString("EVAL does not support type [unsupported] as the return data type of expression [message]") - ); - } - public void testResolveDenseVector() { FieldCapabilitiesResponse caps = FieldCapabilitiesResponse.builder() .withIndexResponses( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index 922e38082c522..77849d77ac28a 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -18,6 +18,7 @@ import org.elasticsearch.xpack.esql.core.expression.FoldContext; import org.elasticsearch.xpack.esql.core.expression.MetadataAttribute; import org.elasticsearch.xpack.esql.core.expression.UnresolvedTimestamp; +import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.core.type.EsField; import org.elasticsearch.xpack.esql.core.type.UnsupportedEsField; import org.elasticsearch.xpack.esql.index.EsIndex; @@ -673,6 +674,28 @@ public void testTypeConflictTextUnmappedNoCast() { } } + public void testSameMappingHashNotPartiallyUnmapped() { + assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); + + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "long")), + fieldCapabilitiesIndexResponse("bar", fieldResponseMap("message", "long")) + ), + List.of() + ); + var resolutions = indexResolutions(mergedResolution("foo,bar", caps)); + TestAnalyzer ta = analyzer(); + for (var entry : resolutions.entrySet()) { + ta.addIndex(entry.getKey().indexPattern(), entry.getValue()); + } + var plan = ta.statement(setUnmappedLoad("FROM foo, bar | EVAL x = message + 1")); + var limit = as(plan, Limit.class); + var eval = as(limit.child(), org.elasticsearch.xpack.esql.plan.logical.Eval.class); + var attr = eval.output().stream().filter(a -> a.name().equals("message")).findFirst().orElseThrow(); + assertThat(attr.dataType(), is(DataType.LONG)); + } + private static final String UNMAPPED_TIMESTAMP_SUFFIX = UnresolvedTimestamp.UNRESOLVED_SUFFIX + Verifier.UNMAPPED_TIMESTAMP_SUFFIX; public void testTbucketWithUnmappedTimestamp() { From 5a9b11e620dc11c65c8103f4179f914664a738a1 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Thu, 26 Mar 2026 14:16:22 +0000 Subject: [PATCH 133/137] [CI] Auto commit changes from spotless --- .../org/elasticsearch/xpack/esql/session/IndexResolver.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java index 7cc8807bfc487..1318a7f4e7351 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/IndexResolver.java @@ -408,10 +408,7 @@ private static CollectedFieldCaps collectFieldCaps(FieldCapabilitiesResponse fie Map> fieldToMappedIndices = new HashMap<>(); for (FieldCapabilitiesIndexResponse response : fieldCapsResponse.getIndexResponses()) { - boolean isNew = indexMappingHashToDuplicateCount.compute( - response.getIndexMappingHash(), - (k, v) -> v == null ? 1 : v + 1 - ) <= 1; + boolean isNew = indexMappingHashToDuplicateCount.compute(response.getIndexMappingHash(), (k, v) -> v == null ? 1 : v + 1) <= 1; String indexName = response.getIndexName(); for (IndexFieldCapabilities fc : response.get().values()) { if (fc.isMetadatafield()) { From 3166bc3a1708fb758346540b084ecb296cae3b17 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 26 Mar 2026 16:08:00 +0200 Subject: [PATCH 134/137] Add more test coverage to double count bug --- .../xpack/esql/CsvTestsDataLoader.java | 1 + .../src/main/resources/unmapped-load.csv-spec | 41 +++++++++++++++++++ .../esql/analysis/AnalyzerUnmappedTests.java | 20 +++++++++ 3 files changed, 62 insertions(+) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java index a03b8719fca85..c666a67df99d8 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java @@ -107,6 +107,7 @@ public class CsvTestsDataLoader { new TestDataset("languages_mixed_numerics").withSetting("lookup-settings.json"), new TestDataset("ul_logs"), new TestDataset("sample_data"), + new TestDataset("sample_data").withIndex("sample_data_copy"), new TestDataset("partial_mapping_sample_data"), new TestDataset("no_mapping_sample_data", "mapping-no_mapping_sample_data.json", "partial_mapping_sample_data.csv").withTypeMapping( Stream.of("timestamp", "client_ip", "event_duration").collect(toMap(k -> k, k -> "keyword")) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index 92022c177e203..ca92f325be310 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -1068,3 +1068,44 @@ FROM partial_mapping_sample_data msg_count:integer | unmapped_messag:keyword 5 | foo ; + +// Regression test: indices with the same mapping hash must not be treated as partially unmapped. +sameMappingHashFullyMapped +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, sample_data_copy +| STATS c = COUNT(*) BY message +| SORT message +; + +c:long | message:keyword +2 | Connected to 10.1.0.1 +2 | Connected to 10.1.0.2 +2 | Connected to 10.1.0.3 +6 | Connection error +2 | Disconnected +; + +// Regression test: two same-hash indices + an unmapped index should still treat the field as partially unmapped. +sameMappingHashWithUnmappedIndex +required_capability: optional_fields_v3 + +SET unmapped_fields="load"\; +FROM sample_data, sample_data_copy, no_mapping_sample_data +| STATS c = COUNT(*) BY message +| SORT message +; + +c:long | message:keyword +1 | 42 +2 | Connected to 10.1.0.1 +1 | Connected to 10.1.0.1! +2 | Connected to 10.1.0.2 +1 | Connected to 10.1.0.2! +2 | Connected to 10.1.0.3 +1 | Connected to 10.1.0.3! +6 | Connection error +3 | Connection error? +2 | Disconnected +; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java index 77849d77ac28a..dadbd144f6529 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerUnmappedTests.java @@ -696,6 +696,26 @@ public void testSameMappingHashNotPartiallyUnmapped() { assertThat(attr.dataType(), is(DataType.LONG)); } + public void testSameMappingHashWithUnmappedIndex() { + assumeTrue("Requires UNMAPPED FIELDS", EsqlCapabilities.Cap.UNMAPPED_FIELDS.isEnabled()); + + FieldCapabilitiesResponse caps = new FieldCapabilitiesResponse( + List.of( + fieldCapabilitiesIndexResponse("foo", fieldResponseMap("message", "long")), + fieldCapabilitiesIndexResponse("bar", fieldResponseMap("message", "long")), + fieldCapabilitiesIndexResponse("baz", Map.of()) + ), + List.of() + ); + var resolutions = indexResolutions(mergedResolution("foo,bar,baz", caps)); + TestAnalyzer ta = analyzer(); + for (var entry : resolutions.entrySet()) { + ta.addIndex(entry.getKey().indexPattern(), entry.getValue()); + } + var e = expectThrows(VerificationException.class, () -> ta.statement(setUnmappedLoad("FROM foo, bar, baz | SORT message"))); + assertThat(e.getMessage(), allOf(containsString("Cannot use field [message]"), containsString("[long] in [bar, foo]"))); + } + private static final String UNMAPPED_TIMESTAMP_SUFFIX = UnresolvedTimestamp.UNRESOLVED_SUFFIX + Verifier.UNMAPPED_TIMESTAMP_SUFFIX; public void testTbucketWithUnmappedTimestamp() { From 9f17be01693521ac36d842c75fd3da2700a7af00 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 26 Mar 2026 17:50:53 +0200 Subject: [PATCH 135/137] Rename test to avoid star expansions in existing tests --- .../java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java | 2 +- .../qa/testFixtures/src/main/resources/unmapped-load.csv-spec | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java index c666a67df99d8..cb5445d8d8113 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java @@ -107,7 +107,7 @@ public class CsvTestsDataLoader { new TestDataset("languages_mixed_numerics").withSetting("lookup-settings.json"), new TestDataset("ul_logs"), new TestDataset("sample_data"), - new TestDataset("sample_data").withIndex("sample_data_copy"), + new TestDataset("sample_data").withIndex("cloned_sample_data"), new TestDataset("partial_mapping_sample_data"), new TestDataset("no_mapping_sample_data", "mapping-no_mapping_sample_data.json", "partial_mapping_sample_data.csv").withTypeMapping( Stream.of("timestamp", "client_ip", "event_duration").collect(toMap(k -> k, k -> "keyword")) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec index ca92f325be310..c954ee5010805 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/unmapped-load.csv-spec @@ -1074,7 +1074,7 @@ sameMappingHashFullyMapped required_capability: optional_fields_v3 SET unmapped_fields="load"\; -FROM sample_data, sample_data_copy +FROM sample_data, cloned_sample_data | STATS c = COUNT(*) BY message | SORT message ; @@ -1092,7 +1092,7 @@ sameMappingHashWithUnmappedIndex required_capability: optional_fields_v3 SET unmapped_fields="load"\; -FROM sample_data, sample_data_copy, no_mapping_sample_data +FROM sample_data, cloned_sample_data, no_mapping_sample_data | STATS c = COUNT(*) BY message | SORT message ; From 9e3e7aaa6a86806cf4669c3b79835cc6bfa329c9 Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 26 Mar 2026 18:43:10 +0200 Subject: [PATCH 136/137] Fix yamlRestTest --- .../rest-api-spec/test/esql/260_flattened_subfield.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/260_flattened_subfield.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/260_flattened_subfield.yml index dc1a5e13abad2..27f6a7e560591 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/260_flattened_subfield.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/260_flattened_subfield.yml @@ -121,7 +121,7 @@ setup: - match: { error.type: verification_exception } - contains: { error.reason: 'Found 1 problem' } - - contains: { error.reason: 'line 1:56: Cannot use field [foo.bar] due to ambiguities being mapped as [2] incompatible types: [keyword] enforced by INSIST command, and [unsupported] in index mappings' } + - contains: { error.reason: 'line 1:56: Cannot use field [foo.bar] due to ambiguities being mapped as [2] incompatible types: [keyword] enforced by INSIST command, [unsupported] in [index4]' } --- 'loading from two indices with different mappings 3': From 54acdb494cc8a641964ab5dc3c9f362447d326da Mon Sep 17 00:00:00 2001 From: Gal Lalouche Date: Thu, 26 Mar 2026 21:36:51 +0200 Subject: [PATCH 137/137] Fix BWC --- .../xpack/esql/core/type/MultiTypeEsField.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java index 5a42e5ed67e08..46a2b5afa17c3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/core/type/MultiTypeEsField.java @@ -76,9 +76,9 @@ public void writeContent(StreamOutput out) throws IOException { out.writeBoolean(isAggregatable()); out.writeMap(getIndexToConversionExpressions(), (o, v) -> out.writeNamedWriteable(v)); writeTimeSeriesFieldType(out); - out.writeOptionalNamedWriteable( - out.getTransportVersion().supports(POTENTIALLY_UNMAPPED_EXPRESSION) ? potentiallyUnmappedExpression : null - ); + if (out.getTransportVersion().supports(POTENTIALLY_UNMAPPED_EXPRESSION)) { + out.writeOptionalNamedWriteable(potentiallyUnmappedExpression); + } } public String getWriteableName(TransportVersion transportVersion) {