Skip to content

Commit

Permalink
ESQL: Correctly compute Rename's output (elastic#110968)
Browse files Browse the repository at this point in the history
Calling Rename.output() previously returned wrong results.

Since elastic#110488, instead it throws an IllegalStateException. That leads to test failures in the EsqlNodeSubclassTests because e.g. MvExpandExec and FieldExtractExec eagerly calls .output() on its child when it's being constructed, and the child can be a fragment containing a Rename.
  • Loading branch information
alex-spies authored Jul 17, 2024
1 parent 272f635 commit 7df1b06
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
*/
package org.elasticsearch.xpack.esql.core.rule;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.logging.LogManager;
import org.elasticsearch.logging.Logger;
import org.elasticsearch.xpack.esql.core.tree.Node;
import org.elasticsearch.xpack.esql.core.util.ReflectionUtils;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.elasticsearch.common.logging.HeaderWarning;
import org.elasticsearch.common.logging.LoggerMessageFormat;
import org.elasticsearch.compute.data.Block;
import org.elasticsearch.logging.Logger;
import org.elasticsearch.xpack.core.enrich.EnrichPolicy;
import org.elasticsearch.xpack.esql.Column;
import org.elasticsearch.xpack.esql.EsqlIllegalArgumentException;
Expand Down Expand Up @@ -383,7 +384,7 @@ private LocalRelation tableMapAsRelation(Source source, Map<String, Column> mapT
}
}

private static class ResolveRefs extends BaseAnalyzerRule {
public static class ResolveRefs extends BaseAnalyzerRule {
@Override
protected LogicalPlan doRule(LogicalPlan plan) {
if (plan.childrenResolved() == false) {
Expand Down Expand Up @@ -575,20 +576,28 @@ private LogicalPlan resolveLookup(Lookup l, List<Attribute> childrenOutput) {
}

private Attribute maybeResolveAttribute(UnresolvedAttribute ua, List<Attribute> childrenOutput) {
return maybeResolveAttribute(ua, childrenOutput, log);
}

private static Attribute maybeResolveAttribute(UnresolvedAttribute ua, List<Attribute> childrenOutput, Logger logger) {
if (ua.customMessage()) {
return ua;
}
return resolveAttribute(ua, childrenOutput);
return resolveAttribute(ua, childrenOutput, logger);
}

private Attribute resolveAttribute(UnresolvedAttribute ua, List<Attribute> childrenOutput) {
return resolveAttribute(ua, childrenOutput, log);
}

private static Attribute resolveAttribute(UnresolvedAttribute ua, List<Attribute> childrenOutput, Logger logger) {
Attribute resolved = ua;
var named = resolveAgainstList(ua, childrenOutput);
// if resolved, return it; otherwise keep it in place to be resolved later
if (named.size() == 1) {
resolved = named.get(0);
if (log.isTraceEnabled() && resolved.resolved()) {
log.trace("Resolved {} to {}", ua, resolved);
if (logger != null && logger.isTraceEnabled() && resolved.resolved()) {
logger.trace("Resolved {} to {}", ua, resolved);
}
} else {
if (named.size() > 0) {
Expand Down Expand Up @@ -724,6 +733,12 @@ private LogicalPlan resolveDrop(Drop drop, List<Attribute> childOutput) {
}

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

return new EsqlProject(rename.source(), rename.child(), projections);
}

public static List<NamedExpression> projectionsForRename(Rename rename, List<Attribute> childrenOutput, Logger logger) {
List<NamedExpression> projections = new ArrayList<>(childrenOutput);

int renamingsCount = rename.renamings().size();
Expand All @@ -736,7 +751,7 @@ private LogicalPlan resolveRename(Rename rename, List<Attribute> childrenOutput)
// remove attributes overwritten by a renaming: `| keep a, b, c | rename a as b`
projections.removeIf(x -> x.name().equals(alias.name()));

var resolved = maybeResolveAttribute(ua, childrenOutput);
var resolved = maybeResolveAttribute(ua, childrenOutput, logger);
if (resolved instanceof UnsupportedAttribute || resolved.resolved()) {
var realiased = (NamedExpression) alias.replaceChildren(List.of(resolved));
projections.replaceAll(x -> x.equals(resolved) ? realiased : x);
Expand Down Expand Up @@ -779,7 +794,7 @@ private LogicalPlan resolveRename(Rename rename, List<Attribute> childrenOutput)
// add unresolved renamings to later trip the Verifier.
projections.addAll(unresolved);

return new EsqlProject(rename.source(), rename.child(), projections);
return projections;
}

private LogicalPlan resolveEnrich(Enrich enrich, List<Attribute> childrenOutput) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@

package org.elasticsearch.xpack.esql.plan.logical;

import org.elasticsearch.xpack.esql.analysis.Analyzer.ResolveRefs;
import org.elasticsearch.xpack.esql.core.expression.Alias;
import org.elasticsearch.xpack.esql.core.expression.Attribute;
import org.elasticsearch.xpack.esql.core.expression.Expressions;
import org.elasticsearch.xpack.esql.core.expression.NamedExpression;
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
import org.elasticsearch.xpack.esql.core.tree.Source;
import org.elasticsearch.xpack.esql.expression.function.UnsupportedAttribute;
Expand All @@ -31,8 +34,10 @@ public List<Alias> renamings() {

@Override
public List<Attribute> output() {
// Rename is mapped to a Project during analysis; we do not compute the output here.
throw new IllegalStateException("Should never reach here.");
// Normally shouldn't reach here, as Rename only exists before resolution.
List<NamedExpression> projectionsAfterResolution = ResolveRefs.projectionsForRename(this, this.child().output(), null);

return Expressions.asAttributes(projectionsAfterResolution);
}

@Override
Expand Down

0 comments on commit 7df1b06

Please sign in to comment.