ESQL: Reuse child outputSet inside the plan where possible (#124611)

Avoid creating outputSet between nodes that passthrough their input

Relates #124395
This commit is contained in:
Costin Leau 2025-03-19 19:44:15 -07:00 committed by GitHub
parent 376abfece9
commit e186b15df2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 27 additions and 7 deletions

View file

@ -0,0 +1,5 @@
pr: 124611
summary: Reuse child `outputSet` inside the plan where possible
area: ES|QL
type: enhancement
issues: []

View file

@ -7,6 +7,7 @@
package org.elasticsearch.xpack.esql.plan.logical; package org.elasticsearch.xpack.esql.plan.logical;
import org.elasticsearch.xpack.esql.core.expression.Attribute; import org.elasticsearch.xpack.esql.core.expression.Attribute;
import org.elasticsearch.xpack.esql.core.expression.AttributeSet;
import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.tree.Source;
import java.util.Collections; import java.util.Collections;
@ -20,6 +21,7 @@ import java.util.Objects;
public abstract class UnaryPlan extends LogicalPlan { public abstract class UnaryPlan extends LogicalPlan {
private final LogicalPlan child; private final LogicalPlan child;
private AttributeSet lazyOutputSet;
protected UnaryPlan(Source source, LogicalPlan child) { protected UnaryPlan(Source source, LogicalPlan child) {
super(source, Collections.singletonList(child)); super(source, Collections.singletonList(child));
@ -42,6 +44,14 @@ public abstract class UnaryPlan extends LogicalPlan {
return child.output(); return child.output();
} }
public AttributeSet outputSet() {
if (lazyOutputSet == null) {
List<Attribute> output = output();
lazyOutputSet = (output == child.output() ? child.outputSet() : new AttributeSet(output));
}
return lazyOutputSet;
}
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hashCode(child()); return Objects.hashCode(child());

View file

@ -9,14 +9,12 @@ package org.elasticsearch.xpack.esql.plan.physical;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.xpack.esql.core.expression.Attribute;
import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.tree.NodeInfo; import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.tree.Source;
import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput; import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.Objects; import java.util.Objects;
public class FilterExec extends UnaryExec { public class FilterExec extends UnaryExec {
@ -63,11 +61,6 @@ public class FilterExec extends UnaryExec {
return condition; return condition;
} }
@Override
public List<Attribute> output() {
return child().output();
}
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(condition, child()); return Objects.hash(condition, child());

View file

@ -8,6 +8,7 @@
package org.elasticsearch.xpack.esql.plan.physical; package org.elasticsearch.xpack.esql.plan.physical;
import org.elasticsearch.xpack.esql.core.expression.Attribute; import org.elasticsearch.xpack.esql.core.expression.Attribute;
import org.elasticsearch.xpack.esql.core.expression.AttributeSet;
import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.tree.Source;
import java.util.Collections; import java.util.Collections;
@ -17,6 +18,7 @@ import java.util.Objects;
public abstract class UnaryExec extends PhysicalPlan { public abstract class UnaryExec extends PhysicalPlan {
private final PhysicalPlan child; private final PhysicalPlan child;
private AttributeSet lazyOutputSet;
protected UnaryExec(Source source, PhysicalPlan child) { protected UnaryExec(Source source, PhysicalPlan child) {
super(source, Collections.singletonList(child)); super(source, Collections.singletonList(child));
@ -39,6 +41,16 @@ public abstract class UnaryExec extends PhysicalPlan {
return child.output(); return child.output();
} }
@Override
public AttributeSet outputSet() {
if (lazyOutputSet == null) {
List<Attribute> output = output();
lazyOutputSet = (output == child.output() ? child.outputSet() : new AttributeSet(output));
return lazyOutputSet;
}
return lazyOutputSet;
}
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hashCode(child()); return Objects.hashCode(child());