Skip to content

Guard unresolved canonicalization in aggregate rewrite#145332

Closed
MattAlp wants to merge 2 commits intoelastic:mainfrom
MattAlp:fix/esql-144252-unresolved-step-canonicalization
Closed

Guard unresolved canonicalization in aggregate rewrite#145332
MattAlp wants to merge 2 commits intoelastic:mainfrom
MattAlp:fix/esql-144252-unresolved-step-canonicalization

Conversation

@MattAlp
Copy link
Copy Markdown
Contributor

@MattAlp MattAlp commented Mar 31, 2026

This bug was caused by ReplaceAggregateNestedExpressionWithEval calling canonical() on unresolved expressions (for example unresolved synthetic PromQL step), which ends up calling dataType() and throwing UnresolvedException. The fix is to canonicalize only resolved expressions and use unresolved expressions as-is for dedup keys, so we avoid internal optimizer crashes and continue to return normal user-facing errors. Added tests cover both the rule-level unresolved step case and a PromQL query path that previously hit this failure.

This is separate from #145307, I think we want to have a bit of hardening in the optimizer separate from the PromQL-to-ESQL validation steps.

Avoid canonical() on unresolved expressions in
ReplaceAggregateNestedExpressionWithEval so unresolved synthetic
step attributes no longer throw UnresolvedException during optimizer
dedup. Add rule-level and PromQL regressions covering the failure.
@MattAlp MattAlp requested review from alex-spies and felixbarny and removed request for alex-spies March 31, 2026 13:18
@elasticsearchmachine elasticsearchmachine added v9.4.0 Team:Analytics Meta label for analytical engine team (ESQL/Aggs/Geo) labels Mar 31, 2026
@elasticsearchmachine
Copy link
Copy Markdown
Collaborator

Pinging @elastic/es-analytical-engine (Team:Analytics)

@elasticsearchmachine
Copy link
Copy Markdown
Collaborator

Hi @MattAlp, I've created a changelog YAML for you.

Copy link
Copy Markdown
Contributor

@alex-spies alex-spies left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @MattAlp !

I would like to take a different approach, because unresolved expressions shouldn't even pass through the verifier. If we let them through, we have no guarantee anymore that we can call .dataType on expressions further down in the optimization pipeline. (We lose an invariant.) That applies to other method calls that are only valid on resolved expressions as well, and would mean that we need to code extra defensively in the optimizer because PromQL queries may have unresolved expressions.

Comment on lines +197 to +199
private static Expression canonicalIfResolved(Expression expression) {
return expression.resolved() ? expression.canonical() : expression;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unresolved expressions shouldn't reach here. If they did, the verifier messed up.

This needs to be caught earlier.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, the original issue arises because the PromQL path builds plans differently and sidesteps our invariants + guards (as you mentioned).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're also planning to move the promql translation from the optimization phase to the analysis phase. That should also help with cases like this as it would be caught by the post analysis verifier. See also #145384.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thanks @felixbarny ! That seems like the right direction. Let us know if you find friction or this otherwise "doesn't fit in" with the usual flow of ESQL queries.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MattAlp
Copy link
Copy Markdown
Contributor Author

MattAlp commented Apr 8, 2026

Closing in favor of a different design post-verification-discussions

@MattAlp MattAlp closed this Apr 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

:Analytics/ES|QL AKA ESQL >bug Team:Analytics Meta label for analytical engine team (ESQL/Aggs/Geo) v9.4.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants