-
Notifications
You must be signed in to change notification settings - Fork 25.6k
ESQL: Dependency check for binary plans #118326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
d37eea4
c5116f1
0d0ecfb
e9a94c3
410b966
5eb9f5f
52373af
ea5f24e
967a0a7
9e77600
c20bb1e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,6 @@ | |
import org.elasticsearch.xpack.esql.core.expression.Attribute; | ||
import org.elasticsearch.xpack.esql.core.expression.Expressions; | ||
import org.elasticsearch.xpack.esql.optimizer.rules.PlanConsistencyChecker; | ||
import org.elasticsearch.xpack.esql.plan.physical.AggregateExec; | ||
import org.elasticsearch.xpack.esql.plan.physical.FieldExtractExec; | ||
import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; | ||
|
||
|
@@ -36,11 +35,6 @@ public Collection<Failure> verify(PhysicalPlan plan) { | |
Failures depFailures = new Failures(); | ||
|
||
plan.forEachDown(p -> { | ||
if (p instanceof AggregateExec agg) { | ||
var exclude = Expressions.references(agg.ordinalAttributes()); | ||
DEPENDENCY_CHECK.checkPlan(p, exclude, depFailures); | ||
Comment on lines
-48
to
-49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Simplified by excluding the ordinal attributes already in |
||
return; | ||
} | ||
if (p instanceof FieldExtractExec fieldExtractExec) { | ||
Attribute sourceAttribute = fieldExtractExec.sourceAttribute(); | ||
if (sourceAttribute == null) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,8 @@ | |
import org.elasticsearch.xpack.esql.core.expression.AttributeSet; | ||
import org.elasticsearch.xpack.esql.core.expression.NameId; | ||
import org.elasticsearch.xpack.esql.plan.QueryPlan; | ||
import org.elasticsearch.xpack.esql.plan.logical.BinaryPlan; | ||
import org.elasticsearch.xpack.esql.plan.physical.BinaryExec; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
|
@@ -26,17 +28,26 @@ public class PlanConsistencyChecker<P extends QueryPlan<P>> { | |
* {@link org.elasticsearch.xpack.esql.common.Failure Failure}s to the {@link Failures} object. | ||
*/ | ||
public void checkPlan(P p, Failures failures) { | ||
checkPlan(p, AttributeSet.EMPTY, failures); | ||
} | ||
|
||
public void checkPlan(P p, AttributeSet exclude, Failures failures) { | ||
AttributeSet refs = p.references(); | ||
AttributeSet input = p.inputSet(); | ||
AttributeSet missing = refs.subtract(input).subtract(exclude); | ||
// TODO: for Joins, we should probably check if the required fields from the left child are actually in the left child, not | ||
// just any child (and analogously for the right child). | ||
if (missing.isEmpty() == false) { | ||
failures.add(fail(p, "Plan [{}] optimized incorrectly due to missing references {}", p.nodeString(), missing)); | ||
if (p instanceof BinaryPlan binaryPlan) { | ||
checkMissing(p, binaryPlan.leftReferences(), binaryPlan.left().outputSet(), "missing references from left hand side", failures); | ||
checkMissing( | ||
p, | ||
binaryPlan.rightReferences(), | ||
binaryPlan.right().outputSet(), | ||
"missing references from right hand side", | ||
failures | ||
); | ||
} else if (p instanceof BinaryExec binaryExec) { | ||
checkMissing(p, binaryExec.leftReferences(), binaryExec.left().outputSet(), "missing references from left hand side", failures); | ||
checkMissing( | ||
p, | ||
binaryExec.rightReferences(), | ||
binaryExec.right().outputSet(), | ||
"missing references from right hand side", | ||
failures | ||
); | ||
} else { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: it'd be nice if we could deduplicate a bit here, maybe with a |
||
checkMissing(p, p.references(), p.inputSet(), "missing references", failures); | ||
} | ||
|
||
Set<String> outputAttributeNames = new HashSet<>(); | ||
|
@@ -49,4 +60,11 @@ public void checkPlan(P p, AttributeSet exclude, Failures failures) { | |
} | ||
} | ||
} | ||
|
||
private void checkMissing(P plan, AttributeSet references, AttributeSet input, String detailErrorMessage, Failures failures) { | ||
AttributeSet missing = references.subtract(input); | ||
if (missing.isEmpty() == false) { | ||
failures.add(fail(plan, "Plan [{}] optimized incorrectly due to {} [{}]", plan.nodeString(), detailErrorMessage, missing)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -184,7 +184,9 @@ public List<Attribute> output() { | |
|
||
@Override | ||
protected AttributeSet computeReferences() { | ||
return mode.isInputPartial() ? new AttributeSet(intermediateAttributes) : Aggregate.computeReferences(aggregates, groupings); | ||
return mode.isInputPartial() | ||
? new AttributeSet(intermediateAttributes) | ||
: Aggregate.computeReferences(aggregates, groupings).subtract(new AttributeSet(ordinalAttributes())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
} | ||
|
||
/** Returns the attributes that can be loaded from ordinals -- no explicit extraction is needed */ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated, but the regenerated docs for this were not committed, yet.