Skip to content

ES|QL: fix null folding of nested COALESCE#140028

Merged
luigidellaquila merged 3 commits intoelastic:mainfrom
luigidellaquila:esql/fix_null_folding_coalesce
Dec 30, 2025
Merged

ES|QL: fix null folding of nested COALESCE#140028
luigidellaquila merged 3 commits intoelastic:mainfrom
luigidellaquila:esql/fix_null_folding_coalesce

Conversation

@luigidellaquila
Copy link
Contributor

@luigidellaquila luigidellaquila commented Dec 29, 2025

COALESCE can't be folded if one of the children is null, even if it's nested inside other expressions.
The same applies to all the functions that don't have Nullability.TRUE (eg. Case and MvUnion)

Fixes: #139344

@elasticsearchmachine elasticsearchmachine added Team:Analytics Meta label for analytical engine team (ESQL/Aggs/Geo) v9.4.0 labels Dec 29, 2025
@elasticsearchmachine
Copy link
Collaborator

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

@elasticsearchmachine
Copy link
Collaborator

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

}
}

if (result != e) {
Copy link
Contributor Author

@luigidellaquila luigidellaquila Dec 30, 2025

Choose a reason for hiding this comment

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

Old QL code, no longer used


foldCoalesce
required_capability: fix_fold_coalesce
ROW x = null| EVAL append_coalesce = MV_APPEND("2", COALESCE(x, "1"))
Copy link
Contributor

Choose a reason for hiding this comment

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

Small spacing typo.

Copy link
Contributor

@mouhc1ne mouhc1ne left a comment

Choose a reason for hiding this comment

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

LGTM.

// so folding it to null would currently break the plan, as we don't create an attribute/channel for that null value.
&& e instanceof GroupingFunction.NonEvaluatableGroupingFunction == false
&& Expressions.anyMatch(e.children(), Expressions::isGuaranteedNull)) {
&& e.children().stream().anyMatch(FoldNull::isNull)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this be:

Suggested change
&& e.children().stream().anyMatch(FoldNull::isNull)) {
isNull(e)) {

Also, highly optional, streams might be heavy.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately it doesn't work. We only have to check that the children are not null, not the parent object, otherwise we'll also try to replace literals (it was my first implementation, and it resulted in several failures)

return e;
}

protected Expression tryReplaceIsNullIsNotNull(Expression e) {
Copy link
Contributor

Choose a reason for hiding this comment

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

👍


foldCoalesce
required_capability: fix_fold_coalesce
ROW x = null| EVAL append_coalesce = MV_APPEND("2", COALESCE(x, "1"))
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe an extra test with a NULL literal?

@luigidellaquila luigidellaquila enabled auto-merge (squash) December 30, 2025 09:19
@luigidellaquila luigidellaquila merged commit b432c7e into elastic:main Dec 30, 2025
35 checks passed
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.

ESQL: FoldNull can wrongly fold COALESCE to null

4 participants