Commit f3ccb70
authored
ESQL: Fix
This PR fixes the issue where `INLINE STATS GROUP BY null` was being
incorrectly pruned by `PruneLeftJoinOnNullMatchingField`.
Fixes elastic#139887
## Problem For query:
```
FROM employees
| INLINE STATS c = COUNT(*) BY n = null
| KEEP c, n
| LIMIT 3
```
During `LogicalPlanOptimizer`:
```
Limit[3[INTEGER],false,false]
\_EsqlProject[[c{r}#2, n{r}#4]]
\_InlineJoin[LEFT,[n{r}#4],[n{r}#4]]
|_Eval[[null[NULL] AS n#4]]
| \_EsRelation[employees][<no-fields>{r$}#7]
\_Aggregate[[n{r}#4],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#2, n{r}#4]]
\_StubRelation[[<no-fields>{r$}#7, n{r}#4]]
```
The following join node:
```
InlineJoin[LEFT,[n{r}#4],[n{r}#4]]
|_Eval[[null[NULL] AS n#4]]
| \_EsRelation[employees][<no-fields>{r$}#7]
\_Aggregate[[n{r}#4],[COUNT(*[KEYWORD],true[BOOLEAN],PT0S[TIME_DURATION]) AS c#2, n{r}#4]]
\_StubRelation[[<no-fields>{r$}#7, n{r}#4]]
```
should NOT have `PruneLeftJoinOnNullMatchingField` applied, because the
right side is an `Aggregate` (originating from `INLINE STATS`). Since
`STATS` supports `GROUP BY null`, the join key being null is a valid use
case. Pruning this join would incorrectly eliminate the aggregation
results, changing the query semantics.
During `LocalLogicalPlanOptimizer`:
```
ProjectExec[[c{r}#2, n{r}#4]]
\_LimitExec[3[INTEGER],null]
\_ExchangeExec[[c{r}#2, n{r}#4],false]
\_FragmentExec[filter=null, estimatedRowSize=0, reducer=[], fragment=[<>
Project[[c{r}#2, n{r}#4]]
\_Limit[3[INTEGER],false,false]
\_InlineJoin[LEFT,[n{r}#4],[n{r}#4]]
|_Eval[[null[NULL] AS n#4]]
| \_EsRelation[employees][<no-fields>{r$}#7]
\_LocalRelation[[c{r}#2, n{r}#4],Page{blocks=[LongVectorBlock[vector=ConstantLongVector[positions=1, value=100]], ConstantNullBlock[positions=1]]}]<>]]
```
The following join node:
```
InlineJoin[LEFT,[n{r}#4],[n{r}#4]]
|_Eval[[null[NULL] AS n#4]]
| \_EsRelation[employees][<no-fields>{r$}#7]
\_LocalRelation[[c{r}#2, n{r}#4],Page{blocks=[LongVectorBlock[vector=ConstantLongVector[positions=1, value=100]], ConstantNullBlock[positions=1]]}]
```
should NOT have `PruneLeftJoinOnNullMatchingField` applied, because the
right side is a `LocalRelation` (the `Aggregate` was optimized into a
`LocalRelation` containing the pre-computed aggregation results).
Pruning this join when the join key is null would discard the valid
aggregation results stored in the `LocalRelation`, incorrectly producing
null values instead of the expected count.
## Solution The fix ensures that `PruneLeftJoinOnNullMatchingField` only
applies to `LOOKUP JOIN` nodes, where `join.right()` is an `EsRelation`.
For `INLINE STATS` joins, the right side can be:
- `Aggregate` (before optimization), or
- `LocalRelation` (after the aggregate is optimized)
By checking `join.right() instanceof EsRelation`, we correctly skip the
pruning optimization for `INLINE STATS` joins, preserving the expected
query results when grouping by null.INLINE STATS GROUP BY null being incorrectly pruned (elastic#140027)1 parent ff7d81a commit f3ccb70
File tree
7 files changed
+487
-5
lines changed- docs/changelog
- x-pack/plugin/esql
- qa/testFixtures/src/main/resources
- src
- main/java/org/elasticsearch/xpack/esql
- action
- optimizer/rules/logical/local
- test/java/org/elasticsearch/xpack/esql/optimizer
7 files changed
+487
-5
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
Lines changed: 119 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5190 | 5190 | | |
5191 | 5191 | | |
5192 | 5192 | | |
| 5193 | + | |
| 5194 | + | |
| 5195 | + | |
| 5196 | + | |
| 5197 | + | |
| 5198 | + | |
| 5199 | + | |
| 5200 | + | |
| 5201 | + | |
| 5202 | + | |
| 5203 | + | |
| 5204 | + | |
| 5205 | + | |
| 5206 | + | |
| 5207 | + | |
| 5208 | + | |
| 5209 | + | |
| 5210 | + | |
| 5211 | + | |
| 5212 | + | |
| 5213 | + | |
| 5214 | + | |
| 5215 | + | |
| 5216 | + | |
| 5217 | + | |
| 5218 | + | |
| 5219 | + | |
| 5220 | + | |
| 5221 | + | |
| 5222 | + | |
| 5223 | + | |
| 5224 | + | |
| 5225 | + | |
| 5226 | + | |
| 5227 | + | |
| 5228 | + | |
| 5229 | + | |
| 5230 | + | |
| 5231 | + | |
| 5232 | + | |
| 5233 | + | |
| 5234 | + | |
| 5235 | + | |
| 5236 | + | |
| 5237 | + | |
| 5238 | + | |
| 5239 | + | |
| 5240 | + | |
| 5241 | + | |
| 5242 | + | |
| 5243 | + | |
| 5244 | + | |
| 5245 | + | |
| 5246 | + | |
| 5247 | + | |
| 5248 | + | |
| 5249 | + | |
| 5250 | + | |
| 5251 | + | |
| 5252 | + | |
| 5253 | + | |
| 5254 | + | |
| 5255 | + | |
| 5256 | + | |
| 5257 | + | |
| 5258 | + | |
| 5259 | + | |
| 5260 | + | |
| 5261 | + | |
| 5262 | + | |
| 5263 | + | |
| 5264 | + | |
| 5265 | + | |
| 5266 | + | |
| 5267 | + | |
| 5268 | + | |
| 5269 | + | |
| 5270 | + | |
| 5271 | + | |
| 5272 | + | |
| 5273 | + | |
| 5274 | + | |
| 5275 | + | |
| 5276 | + | |
| 5277 | + | |
| 5278 | + | |
| 5279 | + | |
| 5280 | + | |
| 5281 | + | |
| 5282 | + | |
| 5283 | + | |
| 5284 | + | |
| 5285 | + | |
| 5286 | + | |
| 5287 | + | |
| 5288 | + | |
| 5289 | + | |
| 5290 | + | |
| 5291 | + | |
| 5292 | + | |
| 5293 | + | |
| 5294 | + | |
| 5295 | + | |
| 5296 | + | |
| 5297 | + | |
| 5298 | + | |
| 5299 | + | |
| 5300 | + | |
| 5301 | + | |
| 5302 | + | |
| 5303 | + | |
| 5304 | + | |
| 5305 | + | |
| 5306 | + | |
| 5307 | + | |
| 5308 | + | |
| 5309 | + | |
| 5310 | + | |
| 5311 | + | |
Lines changed: 2 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
430 | 430 | | |
431 | 431 | | |
432 | 432 | | |
433 | | - | |
| 433 | + | |
434 | 434 | | |
435 | 435 | | |
436 | 436 | | |
437 | 437 | | |
438 | 438 | | |
439 | 439 | | |
440 | | - | |
441 | 440 | | |
442 | | - | |
| 441 | + | |
443 | 442 | | |
444 | 443 | | |
445 | 444 | | |
| |||
Lines changed: 11 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1886 | 1886 | | |
1887 | 1887 | | |
1888 | 1888 | | |
1889 | | - | |
| 1889 | + | |
1890 | 1890 | | |
1891 | 1891 | | |
1892 | 1892 | | |
| |||
1919 | 1919 | | |
1920 | 1920 | | |
1921 | 1921 | | |
| 1922 | + | |
| 1923 | + | |
| 1924 | + | |
| 1925 | + | |
| 1926 | + | |
| 1927 | + | |
| 1928 | + | |
| 1929 | + | |
| 1930 | + | |
| 1931 | + | |
1922 | 1932 | | |
1923 | 1933 | | |
1924 | 1934 | | |
| |||
Lines changed: 11 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
19 | 20 | | |
20 | 21 | | |
21 | 22 | | |
| |||
36 | 37 | | |
37 | 38 | | |
38 | 39 | | |
39 | | - | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
40 | 50 | | |
41 | 51 | | |
42 | 52 | | |
| |||
0 commit comments