Skip to content

Commit b05bf64

Browse files
ES|QL: manage INLINE STATS count(*) on result sets with no columns (#137017)
1 parent 4ef7757 commit b05bf64

File tree

4 files changed

+69
-10
lines changed

4 files changed

+69
-10
lines changed

docs/changelog/137017.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 137017
2+
summary: Manage INLINE STATS count(*) on result sets with no columns
3+
area: ES|QL
4+
type: bug
5+
issues: []

x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/aggregation/CountAggregatorFunction.java

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,23 +78,42 @@ public int intermediateBlockCount() {
7878
}
7979

8080
private int blockIndex() {
81-
return countAll ? 0 : channels.get(0);
81+
// In case of countAll, block index is irrelevant.
82+
// Page.positionCount should be used instead,
83+
// because the page could have zero blocks
84+
// (drop all columns scenario)
85+
return countAll ? -1 : channels.get(0);
8286
}
8387

8488
@Override
8589
public void addRawInput(Page page, BooleanVector mask) {
86-
Block block = page.getBlock(blockIndex());
87-
LongState state = this.state;
88-
int count;
89-
if (mask.isConstant()) {
90-
if (mask.getBoolean(0) == false) {
91-
return;
90+
if (countAll) {
91+
// this will work also when the page has no blocks
92+
if (mask.isConstant() && mask.getBoolean(0)) {
93+
state.longValue(state.longValue() + page.getPositionCount());
94+
} else {
95+
int count = 0;
96+
for (int i = 0; i < mask.getPositionCount(); i++) {
97+
if (mask.getBoolean(i)) {
98+
count++;
99+
}
100+
}
101+
state.longValue(state.longValue() + count);
92102
}
93-
count = countAll ? block.getPositionCount() : block.getTotalValueCount();
94103
} else {
95-
count = countMasked(block, mask);
104+
Block block = page.getBlock(blockIndex());
105+
LongState state = this.state;
106+
int count;
107+
if (mask.isConstant()) {
108+
if (mask.getBoolean(0) == false) {
109+
return;
110+
}
111+
count = block.getTotalValueCount();
112+
} else {
113+
count = countMasked(block, mask);
114+
}
115+
state.longValue(state.longValue() + count);
96116
}
97-
state.longValue(state.longValue() + count);
98117
}
99118

100119
private int countMasked(Block block, BooleanVector mask) {

x-pack/plugin/esql/qa/testFixtures/src/main/resources/inlinestats.csv-spec

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4363,3 +4363,32 @@ from employees
43634363
c:long
43644364
1
43654365
;
4366+
4367+
4368+
inlineStatsKeepDropCountStar
4369+
required_capability: inline_stats_with_no_columns
4370+
4371+
from employees
4372+
| keep emp_no
4373+
| drop emp_no
4374+
| inline stats c = count(*)
4375+
| limit 3
4376+
;
4377+
4378+
c:long
4379+
100
4380+
100
4381+
100
4382+
;
4383+
4384+
rowInlineStatsKeepDropCountStar
4385+
required_capability: inline_stats_with_no_columns
4386+
4387+
row a = 1
4388+
| drop a
4389+
| inline stats c = count(*)
4390+
;
4391+
4392+
c:long
4393+
1
4394+
;

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,11 +1569,17 @@ public enum Cap {
15691569
* Temporarily forbid the use of an explicit or implicit LIMIT before INLINE STATS.
15701570
*/
15711571
FORBID_LIMIT_BEFORE_INLINE_STATS(INLINE_STATS.enabled),
1572+
15721573
/**
15731574
* Support for the TRANGE function
15741575
*/
15751576
FN_TRANGE,
15761577

1578+
/**
1579+
* https://github.com/elastic/elasticsearch/issues/136851
1580+
*/
1581+
INLINE_STATS_WITH_NO_COLUMNS(INLINE_STATS.enabled),
1582+
15771583
// Last capability should still have a comma for fewer merge conflicts when adding new ones :)
15781584
// This comment prevents the semicolon from being on the previous capability when Spotless formats the file.
15791585
;

0 commit comments

Comments
 (0)