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 384d556165ecd..a430ff21128a7 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 @@ -98,7 +98,6 @@ import org.elasticsearch.xpack.esql.rule.ParameterizedRule; import org.elasticsearch.xpack.esql.rule.ParameterizedRuleExecutor; import org.elasticsearch.xpack.esql.rule.Rule; -import org.elasticsearch.xpack.esql.rule.RuleExecutor; import org.elasticsearch.xpack.esql.session.Configuration; import org.elasticsearch.xpack.esql.telemetry.FeatureMetric; import org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter; @@ -153,10 +152,9 @@ public class Analyzer extends ParameterizedRuleExecutor NO_FIELDS = List.of( new ReferenceAttribute(Source.EMPTY, "", DataType.NULL, Nullability.TRUE, null, true) ); - private static final Iterable> rules; - static { - var init = new Batch<>( + private static final List> RULES = List.of( + new Batch<>( "Initialize", Limiter.ONCE, new ResolveTable(), @@ -164,8 +162,8 @@ public class Analyzer extends ParameterizedRuleExecutor( + ), + new Batch<>( "Resolution", /* * ImplicitCasting must be before ResolveRefs. Because a reference is created for a Bucket in Aggregate's aggregates, @@ -176,16 +174,9 @@ public class Analyzer extends ParameterizedRuleExecutor( - "Finish Analysis", - Limiter.ONCE, - new AddImplicitLimit(), - new AddImplicitForkLimit(), - new UnionTypesCleanup() - ); - rules = List.of(init, resolution, finish); - } + ), + new Batch<>("Finish Analysis", Limiter.ONCE, new AddImplicitLimit(), new AddImplicitForkLimit(), new UnionTypesCleanup()) + ); private final Verifier verifier; @@ -208,8 +199,8 @@ public LogicalPlan verify(LogicalPlan plan, BitSet partialMetrics) { } @Override - protected Iterable> batches() { - return rules; + protected List> batches() { + return RULES; } private static class ResolveTable extends ParameterizedAnalyzerRule { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LocalLogicalPlanOptimizer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LocalLogicalPlanOptimizer.java index 3da07e9485af7..188ea200c89fe 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LocalLogicalPlanOptimizer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LocalLogicalPlanOptimizer.java @@ -21,7 +21,7 @@ import java.util.ArrayList; import java.util.List; -import static java.util.Arrays.asList; +import static org.elasticsearch.common.util.CollectionUtils.arrayAsArrayList; import static org.elasticsearch.xpack.esql.optimizer.LogicalPlanOptimizer.cleanup; import static org.elasticsearch.xpack.esql.optimizer.LogicalPlanOptimizer.operators; @@ -33,30 +33,32 @@ */ public class LocalLogicalPlanOptimizer extends ParameterizedRuleExecutor { + private static final List> RULES = replaceRules( + arrayAsArrayList( + new Batch<>( + "Local rewrite", + Limiter.ONCE, + new ReplaceTopNWithLimitAndSort(), + new ReplaceMissingFieldWithNull(), + new InferIsNotNull(), + new InferNonNullAggConstraint() + ), + operators(), + cleanup() + ) + ); + public LocalLogicalPlanOptimizer(LocalLogicalOptimizerContext localLogicalOptimizerContext) { super(localLogicalOptimizerContext); } @Override protected List> batches() { - var local = new Batch<>( - "Local rewrite", - Limiter.ONCE, - new ReplaceTopNWithLimitAndSort(), - new ReplaceMissingFieldWithNull(), - new InferIsNotNull(), - new InferNonNullAggConstraint() - ); - - var rules = new ArrayList>(); - rules.add(local); - // TODO: if the local rules haven't touched the tree, the rest of the rules can be skipped - rules.addAll(asList(operators(), cleanup())); - return replaceRules(rules); + return RULES; } @SuppressWarnings("unchecked") - private List> replaceRules(List> listOfRules) { + private static List> replaceRules(List> listOfRules) { List> newBatches = new ArrayList<>(listOfRules.size()); for (var batch : listOfRules) { var rules = batch.rules(); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizer.java index a865f784137ad..0798bf388eeb1 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizer.java @@ -26,14 +26,14 @@ import java.util.Collection; import java.util.List; -import static java.util.Arrays.asList; - /** * Manages field extraction and pushing parts of the query into Lucene. (Query elements that are not pushed into Lucene are executed via * the compute engine) */ public class LocalPhysicalPlanOptimizer extends ParameterizedRuleExecutor { + private static final List> RULES = rules(true); + private final PhysicalVerifier verifier = PhysicalVerifier.INSTANCE; public LocalPhysicalPlanOptimizer(LocalPhysicalOptimizerContext context) { @@ -54,13 +54,12 @@ PhysicalPlan verify(PhysicalPlan plan) { @Override protected List> batches() { - return rules(true); + return RULES; } - protected List> rules(boolean optimizeForEsSource) { + protected static List> rules(boolean optimizeForEsSource) { List> esSourceRules = new ArrayList<>(6); esSourceRules.add(new ReplaceSourceAttributes()); - if (optimizeForEsSource) { esSourceRules.add(new PushTopNToSource()); esSourceRules.add(new PushLimitToSource()); @@ -81,7 +80,6 @@ protected List> rules(boolean optimizeForEsSource) { new SpatialDocValuesExtraction(), new SpatialShapeBoundsExtraction() ); - return asList(pushdown, fieldExtraction); + return List.of(pushdown, fieldExtraction); } - } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizer.java index 49b11f93e1493..06e40bee8b08b 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizer.java @@ -64,11 +64,10 @@ import org.elasticsearch.xpack.esql.optimizer.rules.logical.TranslateMetricsAggregate; import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.esql.rule.ParameterizedRuleExecutor; +import org.elasticsearch.xpack.esql.rule.RuleExecutor; import java.util.List; -import static java.util.Arrays.asList; - /** *

This class is part of the planner

*

Global optimizations based strictly on the structure of the query (i.e. not factoring in information about the backing indices). @@ -93,6 +92,14 @@ */ public class LogicalPlanOptimizer extends ParameterizedRuleExecutor { + private static final List> RULES = List.of( + substitutions(), + operators(), + new Batch<>("Skip Compute", new SkipQueryOnLimitZero()), + cleanup(), + new Batch<>("Set as Optimized", Limiter.ONCE, new SetAsOptimized()) + ); + private final LogicalVerifier verifier = LogicalVerifier.INSTANCE; public LogicalPlanOptimizer(LogicalOptimizerContext optimizerContext) { @@ -112,14 +119,7 @@ public LogicalPlan optimize(LogicalPlan verified) { @Override protected List> batches() { - return rules(); - } - - protected static List> rules() { - var skip = new Batch<>("Skip Compute", new SkipQueryOnLimitZero()); - var label = new Batch<>("Set as Optimized", Limiter.ONCE, new SetAsOptimized()); - - return asList(substitutions(), operators(), skip, cleanup(), label); + return RULES; } protected static Batch substitutions() { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizer.java index 19f6bc810d01f..2595b5190f7d7 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizer.java @@ -18,14 +18,15 @@ import java.util.Collection; import java.util.List; -import static java.util.Arrays.asList; - /** * This class is part of the planner. Performs global (coordinator) optimization of the physical plan. Local (data-node) optimizations * occur later by operating just on a plan {@link FragmentExec} (subplan). */ public class PhysicalPlanOptimizer extends ParameterizedRuleExecutor { - private static final Iterable> rules = initializeRules(true); + + private static final List> RULES = List.of( + new Batch<>("Plan Boundary", Limiter.ONCE, new ProjectAwayColumns()) + ); private final PhysicalVerifier verifier = PhysicalVerifier.INSTANCE; @@ -45,13 +46,8 @@ PhysicalPlan verify(PhysicalPlan plan) { return plan; } - static List> initializeRules(boolean isOptimizedForEsSource) { - var boundary = new Batch<>("Plan Boundary", Limiter.ONCE, new ProjectAwayColumns()); - return asList(boundary); - } - @Override - protected Iterable> batches() { - return rules; + protected List> batches() { + return RULES; } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestPhysicalPlanOptimizer.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestPhysicalPlanOptimizer.java deleted file mode 100644 index e26779e075b68..0000000000000 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestPhysicalPlanOptimizer.java +++ /dev/null @@ -1,25 +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.optimizer; - -import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; -import org.elasticsearch.xpack.esql.rule.RuleExecutor; - -public class TestPhysicalPlanOptimizer extends PhysicalPlanOptimizer { - - private static final Iterable> rules = initializeRules(false); - - public TestPhysicalPlanOptimizer(PhysicalOptimizerContext context) { - super(context); - } - - @Override - protected Iterable> batches() { - return rules; - } -}