Skip to content

Commit 42d08f1

Browse files
authored
Merge pull request ClickHouse#87193 from ClickHouse/backport/25.8/87014
Backport ClickHouse#87014 to 25.8: Fix uniqExact incorrect result with ROLLUP/CUBE
2 parents 44e9e1a + 7240465 commit 42d08f1

File tree

3 files changed

+97
-2
lines changed

3 files changed

+97
-2
lines changed

src/AggregateFunctions/UniqExactSet.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ class UniqExactSet
132132
}
133133
else
134134
{
135-
auto & lhs = asTwoLevel();
135+
auto & lhs = asTwoLevelChecked();
136136

137137
if (other.isSingleLevel())
138138
return lhs.merge(other.asSingleLevel());
@@ -225,6 +225,7 @@ class UniqExactSet
225225
/// To convert set to two level before merging (we cannot just call convertToTwoLevel() on right hand side set, because it is declared const).
226226
std::shared_ptr<TwoLevelSet> getTwoLevelSet() const
227227
{
228+
doDeepCopyIfNeeded();
228229
return two_level_set ? two_level_set : std::make_shared<TwoLevelSet>(asSingleLevel());
229230
}
230231

@@ -243,10 +244,28 @@ class UniqExactSet
243244
SingleLevelSet & asSingleLevel() { return single_level_set; }
244245
const SingleLevelSet & asSingleLevel() const { return single_level_set; }
245246

247+
TwoLevelSet & asTwoLevelChecked()
248+
{
249+
doDeepCopyIfNeeded();
250+
return *two_level_set;
251+
}
252+
246253
TwoLevelSet & asTwoLevel() { return *two_level_set; }
247254
const TwoLevelSet & asTwoLevel() const { return *two_level_set; }
248255

256+
/// Needed when a row can participate in more than one merge, e.g., ROLLUP/CUBE
257+
void doDeepCopyIfNeeded() const
258+
{
259+
if (two_level_set && two_level_set.use_count() > 1)
260+
{
261+
auto copy = std::make_shared<TwoLevelSet>(two_level_set->size());
262+
for (size_t i = 0; i < two_level_set->NUM_BUCKETS; ++i)
263+
copy->impls[i].merge(two_level_set->impls[i]);
264+
two_level_set = std::move(copy);
265+
}
266+
}
267+
249268
SingleLevelSet single_level_set;
250-
std::shared_ptr<TwoLevelSet> two_level_set;
269+
mutable std::shared_ptr<TwoLevelSet> two_level_set;
251270
};
252271
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--- ROLLUP ---
2+
1071106 999994
3+
1071102 999994
4+
0 1999988
5+
--- CUBE ---
6+
1071106 999994
7+
1071102 999994
8+
0 1999988
9+
--- totals ---
10+
1071106 999994
11+
1071102 999994
12+
13+
0 1999988
14+
--- grouping sets ---
15+
1071106 999994
16+
1071102 999994
17+
0 1999988
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
set max_threads=4;
2+
3+
create table test(c1 Int64, c2 Int64)
4+
Engine=MergeTree ORDER BY c2 AS
5+
WITH gen as
6+
(SELECT xxHash32(number) % 1000000 AS u1,
7+
xxHash32(number+12345) % 1000000 AS u2
8+
FROM numbers(1e6))
9+
SELECT
10+
1071106,
11+
5+(1 + 151703 * ((2 * u1) * (2 * u2)))
12+
FROM gen
13+
union all
14+
SELECT
15+
1071102,
16+
8+(1 + 151693 * ((2 * u1) * (2 * u2)))
17+
FROM gen;
18+
19+
select '--- ROLLUP ---' format TSVRaw;
20+
SELECT
21+
c1,
22+
uniqExact(c2)
23+
FROM test
24+
GROUP BY c1
25+
WITH ROLLUP
26+
ORDER BY c1 DESC;
27+
28+
select '--- CUBE ---' format TSVRaw;
29+
30+
SELECT
31+
c1,
32+
uniqExact(c2)
33+
FROM test
34+
GROUP BY c1
35+
WITH CUBE
36+
ORDER BY c1 DESC;
37+
38+
select '--- totals ---' format TSVRaw;
39+
40+
SELECT
41+
c1,
42+
uniqExact(c2)
43+
FROM test
44+
GROUP BY c1
45+
WITH TOTALS
46+
ORDER BY c1 DESC;
47+
48+
select '--- grouping sets ---' format TSVRaw;
49+
50+
SELECT
51+
c1,
52+
uniqExact(c2)
53+
FROM test
54+
GROUP BY
55+
GROUPING SETS(
56+
(c1),
57+
()
58+
)
59+
ORDER BY c1 DESC;

0 commit comments

Comments
 (0)