-
Notifications
You must be signed in to change notification settings - Fork 24.3k
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
ESQL: Fix missing refs due to pruning renamed grouping columns #107328
ESQL: Fix missing refs due to pruning renamed grouping columns #107328
Conversation
Pinging @elastic/es-analytical-engine (Team:Analytics) |
Hi @alex-spies, I've created a changelog YAML for you. |
@elasticmachine update branch |
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.
Good catch.
@@ -432,7 +432,7 @@ public void testCombineProjectionWithAggregationAndEval() { | |||
var limit = as(plan, Limit.class); | |||
var agg = as(limit.child(), Aggregate.class); | |||
assertThat(Expressions.names(agg.aggregates()), contains("s", "last_name", "first_name", "k")); | |||
assertThat(Expressions.names(agg.groupings()), contains("last_name", "first_name", "k")); | |||
assertThat(Expressions.names(agg.groupings()), contains("last_name", "first_name")); | |||
} |
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.
👍
for (Expression expr : upperGroupings) { | ||
// All substitutions happen before; groupings must be attributes at this point. | ||
Attribute attr = (Attribute) expr; | ||
replaced.add((Attribute) aliases.resolve(attr, attr)); |
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.
This will lead to a CCE - if there's always an attribute inside the alias (what about c = a + 1), make the aliases be a AttributeMap<Attribute>
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.
This shouldn't cause CCE in practice, but I can use an AttributeMap<Attribute>
. (Still need to cast the expressions under the projection's aliases to attributes, then.)
(I'd prefer not having to cast at all, but our Aggs/Projections don't adequately represent the fact that we don't have general expressions here, but attributes.)
...k/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizer.java
Outdated
Show resolved
Hide resolved
@@ -482,6 +487,27 @@ private static List<NamedExpression> combineProjections( | |||
return replaced; | |||
} | |||
|
|||
private static List<Expression> combineUpperGroupingsAndLowerProjections( |
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.
This method looks quite similar to combineProjections() which is the reused inside projectAggregations().
Have you looked into reusing them on groupings?
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.
I initially wanted to re-use this, but I need to make some assumptions (in the form of casting expressions) that are only true if the upper expressions are groupings. I can probably still combine these, but that might become confusing to read.
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.
Lgtm.
a.source(), | ||
p.child(), | ||
// After substitutions groupings can only contain attributes. | ||
combineUpperGroupingsAndLowerProjections((List<? extends Attribute>) (List<?>) a.groupings(), p.projections()), |
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.
combineUpperGroupingsAndLowerProjections((List<? extends Attribute>) (List<?>) a.groupings(), p.projections()), | |
combineUpperGroupingsAndLowerProjections((List<? extends Attribute>) a.groupings(), p.projections()), |
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.
Ah, sorry, this suggestion is wrong.
Why the double cast though and not call the combining function with a List<Expression>
and cast downstream, since groupings are expected as attributes? Same cast as for the projection list.
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.
Yeah, the double casting is ugly indeed, but necessary as long as we have a list.
Initial version cast further downstream, but moved that up and required Attribute
instead of Expression
per Costin's request.
In case our assumptions about the type end up being wrong, it's going to blow up no matter what and roughly in the same spot; IMHO the way to improve this properly is to bake the invariant that groupings are attributes into our types; but that requires a refactoring that is currently not possible due to reliance on the ql project.
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.
Nevermind, explicitly casting each grouping now per Andrei's suggestion.
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.
Left a suggestion. Otherwise LGTM
...k/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizer.java
Outdated
Show resolved
Hide resolved
...k/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizer.java
Outdated
Show resolved
Hide resolved
Co-authored-by: Andrei Stefan <astefan@users.noreply.github.com>
💔 Backport failed
You can use sqren/backport to manually backport by running |
💚 All backports created successfully
Questions ?Please refer to the Backport tool documentation |
…ic#107328) Sometimes, CombineProjections does not correctly update an aggregation's groupings when combining with a preceding projection. Fix this by resolving any aliases used in the groupings and de-duplicating them. --------- Co-authored-by: Andrei Stefan <astefan@users.noreply.github.com> (cherry picked from commit adaa476) # Conflicts: # x-pack/plugin/esql/qa/testFixtures/src/main/resources/stats.csv-spec # x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java
…) (#107599) Sometimes, CombineProjections does not correctly update an aggregation's groupings when combining with a preceding projection. Fix this by resolving any aliases used in the groupings and de-duplicating them. --------- Co-authored-by: Andrei Stefan <astefan@users.noreply.github.com> (cherry picked from commit adaa476) # Conflicts: # x-pack/plugin/esql/qa/testFixtures/src/main/resources/stats.csv-spec # x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java
Fix #107083, more specifically this remaining case.
Close #107166.
In some cases,
CombineProjections
prunes grouping columns if the column was only renamed. E.g.Notice how the
x
is still in the groupings. Confusingly, the query still got executed correctly in most cases.This PR propagates the renaming
x = y
into the groupings. To be correct, we have to avoid propagating the same reference attribute twice into the grouping (otherwise layout errors occur), so this PR also prunes duplicate groupings: