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 fc04fa2b1636c..d23f66bd5aabd 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 @@ -454,6 +454,8 @@ protected LogicalPlan rule(LogicalPlan plan, AnalyzerContext context) { } final List childrenOutput = new ArrayList<>(); + // Gather all the children's output in case of non-unary plans; even for unaries, we need to copy because we may mutate this to + // simplify resolution of e.g. RENAME. for (LogicalPlan child : plan.children()) { var output = child.output(); childrenOutput.addAll(output); @@ -974,6 +976,10 @@ private LogicalPlan resolveRename(Rename rename, List childrenOutput) return new EsqlProject(rename.source(), rename.child(), projections); } + /** + * This will turn a {@link Rename} into an equivalent {@link Project}. + * Can mutate {@code childrenOutput}; hand this a copy if you want to avoid mutation. + */ public static List projectionsForRename(Rename rename, List childrenOutput, Logger logger) { List projections = new ArrayList<>(childrenOutput); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/logical/Rename.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/logical/Rename.java index c609bfdae87e7..ff3ec96b0caa2 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/logical/Rename.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/logical/Rename.java @@ -18,6 +18,7 @@ import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.expression.function.UnsupportedAttribute; +import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -47,7 +48,11 @@ public List renamings() { @Override public List output() { // Normally shouldn't reach here, as Rename only exists before resolution. - List projectionsAfterResolution = ResolveRefs.projectionsForRename(this, this.child().output(), null); + List projectionsAfterResolution = ResolveRefs.projectionsForRename( + this, + new ArrayList<>(this.child().output()), + null + ); return Expressions.asAttributes(projectionsAfterResolution); }