Skip to content

Commit 8975f24

Browse files
authored
[ESQL] Consolidate EsqlProject into Project (#140238)
1 parent 3237562 commit 8975f24

27 files changed

Lines changed: 507 additions & 505 deletions

docs/reference/query-languages/esql/kibana/definition/inline_cast.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

x-pack/plugin/esql/compute/gen/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ apply plugin: 'elasticsearch.build'
22

33
dependencies {
44
api project(':x-pack:plugin:esql:compute:ann')
5+
implementation project(':libs:core')
56
api 'com.squareup:javapoet:1.13.0'
67
}
78

x-pack/plugin/esql/compute/gen/src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
requires com.squareup.javapoet;
1414
requires org.elasticsearch.compute.ann;
1515
requires java.compiler;
16+
requires org.elasticsearch.base;
1617

1718
exports org.elasticsearch.compute.gen;
1819
exports org.elasticsearch.compute.gen.argument;
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
package org.elasticsearch.compute.gen;
9+
10+
import org.elasticsearch.core.UpdateForV10;
11+
12+
import java.util.Set;
13+
14+
import javax.annotation.processing.Completion;
15+
import javax.annotation.processing.ProcessingEnvironment;
16+
import javax.annotation.processing.Processor;
17+
import javax.annotation.processing.RoundEnvironment;
18+
import javax.lang.model.SourceVersion;
19+
import javax.lang.model.element.AnnotationMirror;
20+
import javax.lang.model.element.Element;
21+
import javax.lang.model.element.ExecutableElement;
22+
import javax.lang.model.element.TypeElement;
23+
24+
/**
25+
* A no-op annotation processor that claims marker annotations like {@code @UpdateForV10}.
26+
* <p>
27+
* These annotations are documentation-only markers (with {@code @Retention(SOURCE)}) used to
28+
* track code that needs cleanup in future versions. Since the ESQL module uses annotation
29+
* processors for code generation, the compiler warns about unclaimed annotations. This
30+
* processor claims them to suppress those warnings.
31+
*/
32+
public class MarkerAnnotationProcessor implements Processor {
33+
34+
@Override
35+
public Set<String> getSupportedOptions() {
36+
return Set.of();
37+
}
38+
39+
@Override
40+
public Set<String> getSupportedAnnotationTypes() {
41+
// Marker annotations that are documentation-only and don't require processing.
42+
return Set.of(UpdateForV10.class.getCanonicalName());
43+
}
44+
45+
@Override
46+
public SourceVersion getSupportedSourceVersion() {
47+
return SourceVersion.RELEASE_21;
48+
}
49+
50+
@Override
51+
public void init(ProcessingEnvironment processingEnvironment) {}
52+
53+
@Override
54+
public Iterable<? extends Completion> getCompletions(
55+
Element element,
56+
AnnotationMirror annotationMirror,
57+
ExecutableElement executableElement,
58+
String s
59+
) {
60+
return Set.of();
61+
}
62+
63+
@Override
64+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) {
65+
return true;
66+
}
67+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
org.elasticsearch.compute.gen.AggregatorProcessor
22
org.elasticsearch.compute.gen.ConsumeProcessor
33
org.elasticsearch.compute.gen.EvaluatorProcessor
4+
org.elasticsearch.compute.gen.MarkerAnnotationProcessor

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

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@
143143
import org.elasticsearch.xpack.esql.plan.logical.join.JoinType;
144144
import org.elasticsearch.xpack.esql.plan.logical.join.JoinTypes;
145145
import org.elasticsearch.xpack.esql.plan.logical.join.LookupJoin;
146-
import org.elasticsearch.xpack.esql.plan.logical.local.EsqlProject;
147146
import org.elasticsearch.xpack.esql.plan.logical.local.LocalRelation;
148147
import org.elasticsearch.xpack.esql.plan.logical.local.LocalSupplier;
149148
import org.elasticsearch.xpack.esql.plan.logical.promql.PromqlCommand;
@@ -908,7 +907,7 @@ private LogicalPlan resolveFork(Fork fork, AnalyzerContext context) {
908907
}
909908

910909
List<String> subPlanColumns = logicalPlan.output().stream().map(Attribute::name).toList();
911-
// We need to add an explicit EsqlProject to align the outputs.
910+
// We need to add an explicit Project to align the outputs.
912911
if (logicalPlan instanceof Project == false || subPlanColumns.equals(forkColumns) == false) {
913912
changed = true;
914913
List<Attribute> newOutput = new ArrayList<>();
@@ -1264,7 +1263,7 @@ private LogicalPlan resolveKeep(Project p, List<Attribute> childOutput) {
12641263
resolvedProjections = new ArrayList<>(priorities.keySet());
12651264
}
12661265

1267-
return new EsqlProject(p.source(), p.child(), resolvedProjections);
1266+
return new Project(p.source(), p.child(), resolvedProjections);
12681267
}
12691268

12701269
private LogicalPlan resolveDrop(Drop drop, List<Attribute> childOutput) {
@@ -1294,13 +1293,13 @@ private LogicalPlan resolveDrop(Drop drop, List<Attribute> childOutput) {
12941293
});
12951294
}
12961295

1297-
return new EsqlProject(drop.source(), drop.child(), resolvedProjections);
1296+
return new Project(drop.source(), drop.child(), resolvedProjections);
12981297
}
12991298

13001299
private LogicalPlan resolveRename(Rename rename, List<Attribute> childrenOutput) {
13011300
List<NamedExpression> projections = projectionsForRename(rename, childrenOutput, log);
13021301

1303-
return new EsqlProject(rename.source(), rename.child(), projections);
1302+
return new Project(rename.source(), rename.child(), projections);
13041303
}
13051304

13061305
/**
@@ -2591,12 +2590,12 @@ private static Map<String, Set<AbstractConvertFunction>> collectConvertFunctions
25912590
* Push down the conversion functions into the child plan by adding an Eval with the new aliases on top of the child plan.
25922591
*/
25932592
private static LogicalPlan maybePushDownConvertFunctionsToChild(LogicalPlan child, List<Alias> aliases, List<Attribute> output) {
2594-
// Fork/UnionAll adds an EsqlProject on top of each child plan during resolveFork, check this pattern before pushing down
2593+
// Fork/UnionAll adds an Project on top of each child plan during resolveFork, check this pattern before pushing down
25952594
// If the pattern doesn't match, something unexpected happened, just return the child as is
2596-
if (aliases.isEmpty() == false && child instanceof EsqlProject esqlProject) {
2597-
LogicalPlan childOfProject = esqlProject.child();
2595+
if (aliases.isEmpty() == false && child instanceof Project project) {
2596+
LogicalPlan childOfProject = project.child();
25982597
Eval eval = new Eval(childOfProject.source(), childOfProject, aliases);
2599-
return new EsqlProject(esqlProject.source(), eval, output);
2598+
return new Project(project.source(), eval, output);
26002599
}
26012600
return child;
26022601
}
@@ -2736,7 +2735,7 @@ private static LogicalPlan implicitCastingUnionAllOutput(
27362735
outputChanged = true;
27372736
}
27382737
}
2739-
// create a new eval for the casting expressions, and push it down under the EsqlProject
2738+
// create a new eval for the casting expressions, and push it down under the Project
27402739
newChildren.add(maybePushDownConvertFunctionsToChild(child, newAliases, newChildOutput));
27412740
}
27422741

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

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ Collection<Failure> verify(LogicalPlan plan, BitSet partialMetrics) {
114114

115115
checkOperationsOnUnsignedLong(p, failures);
116116
checkBinaryComparison(p, failures);
117+
checkUnsupportedAttributeRenaming(p, failures);
117118
checkInsist(p, failures);
118119
checkLimitBeforeInlineStats(p, failures);
119120
});
@@ -152,14 +153,10 @@ else if (p.resolved()) {
152153
}
153154

154155
e.forEachUp(ae -> {
155-
// Special handling for Project and unsupported/union types: disallow renaming them but pass them through otherwise.
156-
if (p instanceof Project || p instanceof Insist) {
157-
if (ae instanceof Alias as && as.child() instanceof UnsupportedAttribute ua) {
158-
failures.add(fail(ae, ua.unresolvedMessage()));
159-
}
160-
if (ae instanceof UnsupportedAttribute) {
161-
return;
162-
}
156+
// UnsupportedAttribute can pass through Project/Insist unchanged.
157+
// Renaming is checked separately in #checkUnsupportedAttributeRenaming.
158+
if ((p instanceof Project || p instanceof Insist) && ae instanceof UnsupportedAttribute) {
159+
return;
163160
}
164161

165162
// Do not fail multiple times in case the children are already unresolved.
@@ -275,6 +272,22 @@ private static void checkInsist(LogicalPlan p, Failures failures) {
275272
}
276273
}
277274

275+
/**
276+
* Check that UnsupportedAttribute is not renamed via Alias in Project or Insist.
277+
* UnsupportedAttribute can pass through these plans unchanged, but renaming is not allowed.
278+
* This check runs unconditionally (not gated by {@link LogicalPlan#resolved()}) because
279+
* {@link Project#expressionsResolved()} treats UnsupportedAttribute as resolved to allow pass-through.
280+
*/
281+
private static void checkUnsupportedAttributeRenaming(LogicalPlan p, Failures failures) {
282+
if (p instanceof Project || p instanceof Insist) {
283+
p.forEachExpression(Alias.class, alias -> {
284+
if (alias.child() instanceof UnsupportedAttribute ua) {
285+
failures.add(fail(alias, ua.unresolvedMessage()));
286+
}
287+
});
288+
}
289+
}
290+
278291
/*
279292
* This is a rudimentary check to prevent INLINE STATS after LIMIT. A LIMIT command can be added by other commands by default,
280293
* the best example being FORK. A more robust solution would be to track the commands that add LIMIT and prevent them from doing so

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,23 +40,23 @@
4040
* to {@code Limit} optimization can be applied.
4141
*
4242
* This rule applies for certain patterns of {@code UnionAll} branches. The branches of a {@code UnionAll}/{@code Fork} plan has a similar
43-
* pattern, as {@code Fork} adds {@code EsqlProject}, an optional {@code Eval} and {@code Limit} on top of its actual children. In case
43+
* pattern, as {@code Fork} adds {@code Project}, an optional {@code Eval} and {@code Limit} on top of its actual children. In case
4444
* there is mismatched data types on the same field across different {@code UnionAll} branches, a {@code ConvertFunction} could also be
4545
* added in the optional {@code Eval}.
4646
*
4747
* If the patterns of the {@code UnionAll} branches do not match the following expected patterns, the rule is not applied.
4848
*
49-
* EsqlProject
49+
* Project
5050
* Eval (optional) - added when the output of each UnionAll branch are not exactly the same
5151
* Limit
5252
* EsRelation
5353
* or
54-
* EsqlProject
54+
* Project
5555
* Eval (optional)
5656
* Limit
5757
* Subquery
5858
* or
59-
* Limit - CombineProjections may remove the EsqlProject on top of the limit
59+
* Limit - CombineProjections may remove the Project on top of the limit
6060
* Subquery
6161
*/
6262
public final class PushDownFilterAndLimitIntoUnionAll extends Rule<LogicalPlan, LogicalPlan> {

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import org.elasticsearch.xpack.esql.plan.logical.Project;
2727
import org.elasticsearch.xpack.esql.plan.logical.Row;
2828
import org.elasticsearch.xpack.esql.plan.logical.join.StubRelation;
29-
import org.elasticsearch.xpack.esql.plan.logical.local.EsqlProject;
3029
import org.elasticsearch.xpack.esql.rule.ParameterizedRule;
3130

3231
import java.util.ArrayList;
@@ -203,7 +202,7 @@ private LogicalPlan transformPotentialInvocation(LogicalPlan plan) {
203202
return plan;
204203
}
205204
// Found a new pushable attribute, discard it *after* use so we don't modify the output.
206-
return new EsqlProject(Source.EMPTY, transformedPlan, transformedPlan.output());
205+
return new Project(Source.EMPTY, transformedPlan, transformedPlan.output());
207206
}
208207

209208
private Expression transformExpression(LogicalPlan nodeWithExpression, Expression e, BlockLoaderExpression ble) {

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/PlanWritables.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.elasticsearch.xpack.esql.plan.logical.join.Join;
3232
import org.elasticsearch.xpack.esql.plan.logical.local.CopyingLocalSupplier;
3333
import org.elasticsearch.xpack.esql.plan.logical.local.EmptyLocalSupplier;
34-
import org.elasticsearch.xpack.esql.plan.logical.local.EsqlProject;
3534
import org.elasticsearch.xpack.esql.plan.logical.local.ImmediateLocalSupplier;
3635
import org.elasticsearch.xpack.esql.plan.logical.local.LocalRelation;
3736
import org.elasticsearch.xpack.esql.plan.physical.AggregateExec;
@@ -79,7 +78,6 @@ public static List<NamedWriteableRegistry.Entry> logical() {
7978
Dissect.ENTRY,
8079
Enrich.ENTRY,
8180
EsRelation.ENTRY,
82-
EsqlProject.ENTRY,
8381
Eval.ENTRY,
8482
Filter.ENTRY,
8583
Grok.ENTRY,
@@ -92,6 +90,7 @@ public static List<NamedWriteableRegistry.Entry> logical() {
9290
MvExpand.ENTRY,
9391
OrderBy.ENTRY,
9492
Project.ENTRY,
93+
Project.V9_ENTRY, // Backward compatibility for reading old "EsqlProject" type
9594
Rerank.ENTRY,
9695
Sample.ENTRY,
9796
Subquery.ENTRY,

0 commit comments

Comments
 (0)