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
SQL: SubSelect unresolved bugfix #55956
Conversation
Pinging @elastic/es-ql (:Query Languages/SQL) |
@@ -722,7 +722,7 @@ protected LogicalPlan rule(LogicalPlan plan) { | |||
} | |||
|
|||
// Try to resolve aggregates and groupings based on the child plan | |||
if (plan instanceof Aggregate) { | |||
if (plan instanceof Aggregate && !plan.resolved() && plan.childrenResolved()) { |
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.
if (plan instanceof Aggregate && !plan.resolved() && plan.childrenResolved()) { | |
if (plan instanceof Aggregate && plan.resolved() == false && plan.childrenResolved()) { |
despite my own prefs.
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.
Considering this condition applies for all ifs inside this rule, I would extract it to the top:
@Override
protected LogicalPlan rule(LogicalPlan plan) {
if (plan.resolved() || plan.childrenResolved() == false) {
return plan;
}
if (plan instanceof Filter) {...
In fact the check for children resolution is present I believe in all analyzer rules so it might make to create a subclass that all other rules extend to avoid having to repeat this bit of code which as we can see, introduces some subtle bugs.
I'm fine with doing it in a follow-up PR to get this in (with the if moved to the top level).
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.
Great set of tests. I'd be great to see some more complex subqueries, but I guess I'm just trying to better understand our own boundaries.
Anyways, LGTM.
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 - thanks for the quick turn-around!
@@ -722,7 +722,7 @@ protected LogicalPlan rule(LogicalPlan plan) { | |||
} | |||
|
|||
// Try to resolve aggregates and groupings based on the child plan | |||
if (plan instanceof Aggregate) { | |||
if (plan instanceof Aggregate && !plan.resolved() && plan.childrenResolved()) { |
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.
Considering this condition applies for all ifs inside this rule, I would extract it to the top:
@Override
protected LogicalPlan rule(LogicalPlan plan) {
if (plan.resolved() || plan.childrenResolved() == false) {
return plan;
}
if (plan instanceof Filter) {...
In fact the check for children resolution is present I believe in all analyzer rules so it might make to create a subclass that all other rules extend to avoid having to repeat this bit of code which as we can see, introduces some subtle bugs.
I'm fine with doing it in a follow-up PR to get this in (with the if moved to the top level).
…o subselect_unresolved_bugfix
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
@@ -610,9 +600,12 @@ private AggGroupingFailure(List<String> expectedGrouping) { | |||
} | |||
|
|||
@Override | |||
protected LogicalPlan rule(LogicalPlan plan) { | |||
protected LogicalPlan rulePlan(LogicalPlan plan) { | |||
if (plan.resolved()) { |
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 don't think this is needed anymore - see AnalyzeRule
which takes care of skipping if the node is resolved and skipResolved
is true (default).
@@ -1312,4 +1303,17 @@ protected boolean skipResolved() { | |||
return true; | |||
} | |||
} | |||
|
|||
abstract static class LogicalPlanAnalyzeRule extends AnalyzeRule<LogicalPlan> { |
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'd pick a different name - maybe DefaultAnalyzeRule
or BaseAnalyzeRule
.
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 was struggling with the name, indeed. I didn't particularly like LogicalPlanAnalyzeRule, but didn't find any better alternatives.
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 like BaseAnalyzeRule
.
return rulePlan(plan); | ||
} | ||
|
||
protected abstract LogicalPlan rulePlan(LogicalPlan plan); |
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.
rulePlan
is repetitive (the method only accepts LogicalPlan
s) - how about doRule
or analyze
?
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. Nice set of tests!
@@ -1312,4 +1303,17 @@ protected boolean skipResolved() { | |||
return true; | |||
} | |||
} | |||
|
|||
abstract static class LogicalPlanAnalyzeRule extends AnalyzeRule<LogicalPlan> { |
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 like BaseAnalyzeRule
.
@@ -0,0 +1,53 @@ | |||
|
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.
Please add the following comment in case someone needs to mute a test in the future:
// To mute tests follow example in file: example.sql-spec
…o subselect_unresolved_bugfix
* Resolve the missing refs only after the aggregate tree is resolved (cherry picked from commit 10167b1)
* Resolve the missing refs only after the aggregate tree is resolved (cherry picked from commit 10167b1)
* Resolve the missing refs only after the aggregate tree is resolved (cherry picked from commit 10167b1)
* Resolve the missing refs only after the aggregate tree is resolved
This fixes an issue where a sub-query was attempted to be resolved at the wrong time in the analysis, generating an error message similar to
org.elasticsearch.xpack.sql.capabilities.UnresolvedException: Invalid call to attribute on an unresolved object ?* AS ?
. Bug introduced with #41964.