Skip to content

Commit e2b5837

Browse files
committed
Modify analyzer and optimizer rules to be sync rules.
1 parent 70de334 commit e2b5837

File tree

79 files changed

+240
-241
lines changed

Some content is hidden

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

79 files changed

+240
-241
lines changed

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ protected List<Batch<LogicalPlan>> batches() {
212212
return RULES;
213213
}
214214

215-
private static class ResolveTable extends ParameterizedAnalyzerRule<UnresolvedRelation, AnalyzerContext> {
215+
private static class ResolveTable extends ParameterizedAnalyzerRule.Sync<UnresolvedRelation, AnalyzerContext> {
216216

217217
@Override
218218
protected LogicalPlan rule(UnresolvedRelation plan, AnalyzerContext context) {
@@ -312,7 +312,7 @@ private static void mappingAsAttributes(List<Attribute> list, Source source, Str
312312
}
313313
}
314314

315-
private static class ResolveEnrich extends ParameterizedAnalyzerRule<Enrich, AnalyzerContext> {
315+
private static class ResolveEnrich extends ParameterizedAnalyzerRule.Sync<Enrich, AnalyzerContext> {
316316

317317
@Override
318318
protected LogicalPlan rule(Enrich plan, AnalyzerContext context) {
@@ -398,7 +398,7 @@ private static NamedExpression createEnrichFieldExpression(
398398
}
399399
}
400400

401-
private static class ResolveInference extends ParameterizedAnalyzerRule<InferencePlan<?>, AnalyzerContext> {
401+
private static class ResolveInference extends ParameterizedAnalyzerRule.Sync<InferencePlan<?>, AnalyzerContext> {
402402
@Override
403403
protected LogicalPlan rule(InferencePlan<?> plan, AnalyzerContext context) {
404404
assert plan.inferenceId().resolved() && plan.inferenceId().foldable();
@@ -426,7 +426,7 @@ protected LogicalPlan rule(InferencePlan<?> plan, AnalyzerContext context) {
426426
}
427427
}
428428

429-
private static class ResolveLookupTables extends ParameterizedAnalyzerRule<Lookup, AnalyzerContext> {
429+
private static class ResolveLookupTables extends ParameterizedAnalyzerRule.Sync<Lookup, AnalyzerContext> {
430430

431431
@Override
432432
protected LogicalPlan rule(Lookup lookup, AnalyzerContext context) {
@@ -474,7 +474,7 @@ private LocalRelation tableMapAsRelation(Source source, Map<String, Column> mapT
474474
}
475475
}
476476

477-
public static class ResolveRefs extends ParameterizedAnalyzerRule<LogicalPlan, AnalyzerContext> {
477+
public static class ResolveRefs extends ParameterizedAnalyzerRule.Sync<LogicalPlan, AnalyzerContext> {
478478
@Override
479479
protected LogicalPlan rule(LogicalPlan plan, AnalyzerContext context) {
480480
if (plan.childrenResolved() == false) {
@@ -1286,7 +1286,7 @@ private static Attribute handleSpecialFields(UnresolvedAttribute u, Attribute na
12861286
return named.withLocation(u.source());
12871287
}
12881288

1289-
private static class ResolveFunctions extends ParameterizedAnalyzerRule<LogicalPlan, AnalyzerContext> {
1289+
private static class ResolveFunctions extends ParameterizedAnalyzerRule.Sync<LogicalPlan, AnalyzerContext> {
12901290

12911291
@Override
12921292
protected LogicalPlan rule(LogicalPlan plan, AnalyzerContext context) {
@@ -1319,7 +1319,7 @@ public static org.elasticsearch.xpack.esql.core.expression.function.Function res
13191319
}
13201320
}
13211321

1322-
private static class AddImplicitLimit extends ParameterizedRule<LogicalPlan, LogicalPlan, AnalyzerContext> {
1322+
private static class AddImplicitLimit extends ParameterizedRule.Sync<LogicalPlan, LogicalPlan, AnalyzerContext> {
13231323
@Override
13241324
public LogicalPlan apply(LogicalPlan logicalPlan, AnalyzerContext context) {
13251325
List<LogicalPlan> limits = logicalPlan.collectFirstChildren(Limit.class::isInstance);
@@ -1338,7 +1338,7 @@ public LogicalPlan apply(LogicalPlan logicalPlan, AnalyzerContext context) {
13381338
}
13391339
}
13401340

1341-
private static class AddImplicitForkLimit extends ParameterizedRule<LogicalPlan, LogicalPlan, AnalyzerContext> {
1341+
private static class AddImplicitForkLimit extends ParameterizedRule.Sync<LogicalPlan, LogicalPlan, AnalyzerContext> {
13421342
private final AddImplicitLimit addImplicitLimit = new AddImplicitLimit();
13431343

13441344
@Override
@@ -1386,7 +1386,7 @@ private BitSet gatherPreAnalysisMetrics(LogicalPlan plan, BitSet b) {
13861386
* </ul>
13871387
* Coalesce(Int, Long) will NOT be converted to Coalesce(Long, Long) or Coalesce(Int, Int).
13881388
*/
1389-
private static class ImplicitCasting extends ParameterizedRule<LogicalPlan, LogicalPlan, AnalyzerContext> {
1389+
private static class ImplicitCasting extends ParameterizedRule.Sync<LogicalPlan, LogicalPlan, AnalyzerContext> {
13901390
@Override
13911391
public LogicalPlan apply(LogicalPlan plan, AnalyzerContext context) {
13921392
// do implicit casting for function arguments
@@ -1634,15 +1634,16 @@ private static Expression processVectorFunction(org.elasticsearch.xpack.esql.cor
16341634
}
16351635

16361636
/**
1637-
* The EsqlIndexResolver will create InvalidMappedField instances for fields that are ambiguous (i.e. have multiple mappings).
1638-
* During {@link ResolveRefs} we do not convert these to UnresolvedAttribute instances, as we want to first determine if they can
1639-
* instead be handled by conversion functions within the query. This rule looks for matching conversion functions and converts
1640-
* those fields into MultiTypeEsField, which encapsulates the knowledge of how to convert these into a single type.
1641-
* This knowledge will be used later in generating the FieldExtractExec with built-in type conversion.
1642-
* Any fields which could not be resolved by conversion functions will be converted to UnresolvedAttribute instances in a later rule
1643-
* (See {@link UnionTypesCleanup} below).
1637+
* {@link ResolveUnionTypes} creates new, synthetic attributes for union types:
1638+
* If there was no {@code AbstractConvertFunction} that resolved multi-type fields in the {@link ResolveUnionTypes} rule,
1639+
* then there could still be some {@code FieldAttribute}s that contain unresolved {@link MultiTypeEsField}s.
1640+
* These need to be converted back to actual {@code UnresolvedAttribute} in order for validation to generate appropriate failures.
1641+
* <p>
1642+
* Finally, if {@code client_ip} is present in 2 indices, once with type {@code ip} and once with type {@code keyword},
1643+
* using {@code EVAL x = to_ip(client_ip)} will create a single attribute @{code $$client_ip$converted_to$ip}.
1644+
* This should not spill into the query output, so we drop such attributes at the end.
16441645
*/
1645-
private static class ResolveUnionTypes extends Rule<LogicalPlan, LogicalPlan> {
1646+
private static class ResolveUnionTypes extends Rule.Sync<LogicalPlan, LogicalPlan> {
16461647

16471648
record TypeResolutionKey(String fieldName, DataType fieldType) {}
16481649

@@ -1652,6 +1653,7 @@ record TypeResolutionKey(String fieldName, DataType fieldType) {}
16521653
public LogicalPlan apply(LogicalPlan plan) {
16531654
unionFieldAttributes = new ArrayList<>();
16541655
return plan.transformUp(LogicalPlan.class, p -> p.childrenResolved() == false ? p : doRule(p));
1656+
16551657
}
16561658

16571659
private LogicalPlan doRule(LogicalPlan plan) {
@@ -1850,7 +1852,7 @@ private static Expression typeSpecificConvert(ConvertFunction convert, Source so
18501852
* using {@code EVAL x = to_ip(client_ip)} will create a single attribute @{code $$client_ip$converted_to$ip}.
18511853
* This should not spill into the query output, so we drop such attributes at the end.
18521854
*/
1853-
private static class UnionTypesCleanup extends Rule<LogicalPlan, LogicalPlan> {
1855+
private static class UnionTypesCleanup extends Rule.Sync<LogicalPlan, LogicalPlan> {
18541856
public LogicalPlan apply(LogicalPlan plan) {
18551857
LogicalPlan planWithCheckedUnionTypes = plan.transformUp(
18561858
LogicalPlan.class,
@@ -1898,7 +1900,7 @@ private static LogicalPlan planWithoutSyntheticAttributes(LogicalPlan plan) {
18981900
/**
18991901
* Cast the union typed fields in EsRelation to date_nanos if they are mixed date and date_nanos types.
19001902
*/
1901-
private static class DateMillisToNanosInEsRelation extends Rule<LogicalPlan, LogicalPlan> {
1903+
private static class DateMillisToNanosInEsRelation extends Rule.Sync<LogicalPlan, LogicalPlan> {
19021904

19031905
private final boolean isSnapshot;
19041906

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/AnalyzerRules.java

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,51 +22,37 @@
2222

2323
public final class AnalyzerRules {
2424

25-
public abstract static class AnalyzerRule<SubPlan extends LogicalPlan> extends Rule<SubPlan, LogicalPlan> {
26-
27-
// transformUp (post-order) - that is first children and then the node
28-
// but with a twist; only if the tree is not resolved or analyzed
29-
@Override
30-
public final LogicalPlan apply(LogicalPlan plan) {
31-
return plan.transformUp(typeToken(), t -> t.analyzed() || skipResolved() && t.resolved() ? t : rule(t));
32-
}
25+
public interface AnalyzerRule<SubPlan extends LogicalPlan> extends Rule<SubPlan, LogicalPlan> {
26+
abstract class Sync<SubPlan extends LogicalPlan> extends Rule.Sync<SubPlan, LogicalPlan> {
27+
// transformUp (post-order) - that is first children and then the node
28+
// but with a twist; only if the tree is not resolved or analyzed
29+
@Override
30+
public final LogicalPlan apply(LogicalPlan plan) {
31+
return plan.transformUp(typeToken(), t -> t.analyzed() || skipResolved() && t.resolved() ? t : rule(t));
32+
}
3333

34-
protected abstract LogicalPlan rule(SubPlan plan);
34+
protected abstract LogicalPlan rule(SubPlan plan);
3535

36-
protected boolean skipResolved() {
37-
return true;
36+
protected boolean skipResolved() {
37+
return true;
38+
}
3839
}
3940
}
4041

41-
public abstract static class ParameterizedAnalyzerRule<SubPlan extends LogicalPlan, P> extends ParameterizedRule<
42-
SubPlan,
43-
LogicalPlan,
44-
P> {
45-
46-
// transformUp (post-order) - that is first children and then the node
47-
// but with a twist; only if the tree is not resolved or analyzed
48-
public final LogicalPlan apply(LogicalPlan plan, P context) {
49-
return plan.transformUp(typeToken(), t -> t.analyzed() || skipResolved() && t.resolved() ? t : rule(t, context));
50-
}
51-
52-
protected abstract LogicalPlan rule(SubPlan plan, P context);
53-
54-
protected boolean skipResolved() {
55-
return true;
56-
}
57-
}
42+
public interface ParameterizedAnalyzerRule<SubPlan extends LogicalPlan, P> extends ParameterizedRule<SubPlan, LogicalPlan, P> {
43+
abstract class Sync<SubPlan extends LogicalPlan, P> extends ParameterizedRule.Sync<SubPlan, LogicalPlan, P> {
44+
// transformUp (post-order) - that is first children and then the node
45+
// but with a twist; only if the tree is not resolved or analyzed
46+
public final LogicalPlan apply(LogicalPlan plan, P context) {
47+
return plan.transformUp(typeToken(), t -> t.analyzed() || skipResolved() && t.resolved() ? t : rule(t, context));
48+
}
5849

59-
public abstract static class BaseAnalyzerRule extends AnalyzerRule<LogicalPlan> {
50+
protected abstract LogicalPlan rule(SubPlan plan, P context);
6051

61-
@Override
62-
protected LogicalPlan rule(LogicalPlan plan) {
63-
if (plan.childrenResolved() == false) {
64-
return plan;
52+
protected boolean skipResolved() {
53+
return true;
6554
}
66-
return doRule(plan);
6755
}
68-
69-
protected abstract LogicalPlan doRule(LogicalPlan plan);
7056
}
7157

7258
public static List<Attribute> maybeResolveAgainstList(

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/PhysicalOptimizerRules.java

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,57 +7,61 @@
77

88
package org.elasticsearch.xpack.esql.optimizer;
99

10+
import org.elasticsearch.xpack.esql.optimizer.rules.logical.OptimizerRules;
1011
import org.elasticsearch.xpack.esql.optimizer.rules.logical.OptimizerRules.TransformDirection;
1112
import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan;
1213
import org.elasticsearch.xpack.esql.rule.ParameterizedRule;
1314
import org.elasticsearch.xpack.esql.rule.Rule;
1415

1516
public class PhysicalOptimizerRules {
1617

17-
public abstract static class ParameterizedOptimizerRule<SubPlan extends PhysicalPlan, P> extends ParameterizedRule<
18-
SubPlan,
19-
PhysicalPlan,
20-
P> {
18+
public interface ParameterizedOptimizerRule<SubPlan extends PhysicalPlan, P> extends ParameterizedRule<SubPlan, PhysicalPlan, P> {
19+
abstract class Sync<SubPlan extends PhysicalPlan, P> extends ParameterizedRule.Sync<SubPlan, PhysicalPlan, P>
20+
implements
21+
ParameterizedOptimizerRule<SubPlan, P> {
2122

22-
private final TransformDirection direction;
23+
private final TransformDirection direction;
2324

24-
public ParameterizedOptimizerRule() {
25-
this(TransformDirection.DOWN);
26-
}
25+
public Sync() {
26+
this(OptimizerRules.TransformDirection.DOWN);
27+
}
2728

28-
protected ParameterizedOptimizerRule(TransformDirection direction) {
29-
this.direction = direction;
30-
}
29+
protected Sync(TransformDirection direction) {
30+
this.direction = direction;
31+
}
3132

32-
@Override
33-
public final PhysicalPlan apply(PhysicalPlan plan, P context) {
34-
return direction == TransformDirection.DOWN
35-
? plan.transformDown(typeToken(), t -> rule(t, context))
36-
: plan.transformUp(typeToken(), t -> rule(t, context));
37-
}
33+
@Override
34+
public final PhysicalPlan apply(PhysicalPlan plan, P context) {
35+
return direction == OptimizerRules.TransformDirection.DOWN
36+
? plan.transformDown(typeToken(), t -> rule(t, context))
37+
: plan.transformUp(typeToken(), t -> rule(t, context));
38+
}
3839

39-
protected abstract PhysicalPlan rule(SubPlan plan, P context);
40+
protected abstract PhysicalPlan rule(SubPlan plan, P context);
41+
}
4042
}
4143

42-
public abstract static class OptimizerRule<SubPlan extends PhysicalPlan> extends Rule<SubPlan, PhysicalPlan> {
44+
public interface OptimizerRule<SubPlan extends PhysicalPlan> extends Rule<SubPlan, PhysicalPlan> {
45+
abstract class Sync<SubPlan extends PhysicalPlan> extends Rule.Sync<SubPlan, PhysicalPlan> implements OptimizerRule<SubPlan> {
4346

44-
private final TransformDirection direction;
47+
private final TransformDirection direction;
4548

46-
public OptimizerRule() {
47-
this(TransformDirection.DOWN);
48-
}
49+
public Sync() {
50+
this(OptimizerRules.TransformDirection.DOWN);
51+
}
4952

50-
protected OptimizerRule(TransformDirection direction) {
51-
this.direction = direction;
52-
}
53+
protected Sync(TransformDirection direction) {
54+
this.direction = direction;
55+
}
5356

54-
@Override
55-
public final PhysicalPlan apply(PhysicalPlan plan) {
56-
return direction == TransformDirection.DOWN
57-
? plan.transformDown(typeToken(), this::rule)
58-
: plan.transformUp(typeToken(), this::rule);
59-
}
57+
@Override
58+
public final PhysicalPlan apply(PhysicalPlan plan) {
59+
return direction == OptimizerRules.TransformDirection.DOWN
60+
? plan.transformDown(typeToken(), this::rule)
61+
: plan.transformUp(typeToken(), this::rule);
62+
}
6063

61-
protected abstract PhysicalPlan rule(SubPlan plan);
64+
protected abstract PhysicalPlan rule(SubPlan plan);
65+
}
6266
}
6367
}

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/BooleanFunctionEqualsElimination.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* This rule must always be placed after {@link LiteralsOnTheRight}
2323
* since it looks at TRUE/FALSE literals' existence on the right hand-side of the {@link Equals}/{@link NotEquals} expressions.
2424
*/
25-
public final class BooleanFunctionEqualsElimination extends OptimizerRules.OptimizerExpressionRule<BinaryComparison> {
25+
public final class BooleanFunctionEqualsElimination extends OptimizerRules.OptimizerExpressionRule.Sync<BinaryComparison> {
2626

2727
public BooleanFunctionEqualsElimination() {
2828
super(OptimizerRules.TransformDirection.UP);

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/BooleanSimplification.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import static org.elasticsearch.xpack.esql.expression.predicate.Predicates.splitOr;
3030
import static org.elasticsearch.xpack.esql.expression.predicate.Predicates.subtract;
3131

32-
public final class BooleanSimplification extends OptimizerRules.OptimizerExpressionRule<ScalarFunction> {
32+
public final class BooleanSimplification extends OptimizerRules.OptimizerExpressionRule.Sync<ScalarFunction> {
3333

3434
public BooleanSimplification() {
3535
super(OptimizerRules.TransformDirection.UP);

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/CombineBinaryComparisons.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import java.util.ArrayList;
2727
import java.util.List;
2828

29-
public final class CombineBinaryComparisons extends OptimizerRules.OptimizerExpressionRule<BinaryLogic> {
29+
public final class CombineBinaryComparisons extends OptimizerRules.OptimizerExpressionRule.Sync<BinaryLogic> {
3030

3131
public CombineBinaryComparisons() {
3232
super(OptimizerRules.TransformDirection.DOWN);

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/CombineDisjunctions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
* This rule does NOT check for type compatibility as that phase has been
4545
* already be verified in the analyzer.
4646
*/
47-
public final class CombineDisjunctions extends OptimizerRules.OptimizerExpressionRule<Or> {
47+
public final class CombineDisjunctions extends OptimizerRules.OptimizerExpressionRule.Sync<Or> {
4848
public CombineDisjunctions() {
4949
super(OptimizerRules.TransformDirection.UP);
5050
}

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/CombineEvals.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Combine multiple Evals into one in order to reduce the number of nodes in a plan.
1616
* TODO: eliminate unnecessary fields inside the eval as well
1717
*/
18-
public final class CombineEvals extends OptimizerRules.OptimizerRule<Eval> {
18+
public final class CombineEvals extends OptimizerRules.OptimizerRule.Sync<Eval> {
1919

2020
public CombineEvals() {
2121
super(OptimizerRules.TransformDirection.UP);

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/CombineProjections.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import java.util.List;
3030
import java.util.Set;
3131

32-
public final class CombineProjections extends OptimizerRules.OptimizerRule<UnaryPlan> {
32+
public final class CombineProjections extends OptimizerRules.OptimizerRule.Sync<UnaryPlan> {
3333
// don't drop groupings from a local plan, as the layout has already been agreed upon
3434
private final boolean local;
3535

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/ConstantFolding.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import org.elasticsearch.xpack.esql.core.expression.Literal;
1212
import org.elasticsearch.xpack.esql.optimizer.LogicalOptimizerContext;
1313

14-
public final class ConstantFolding extends OptimizerRules.OptimizerExpressionRule<Expression> {
14+
public final class ConstantFolding extends OptimizerRules.OptimizerExpressionRule.Sync<Expression> {
1515

1616
public ConstantFolding() {
1717
super(OptimizerRules.TransformDirection.DOWN);

0 commit comments

Comments
 (0)