Merge pull request #67122 from Avogar/variant-aggregate-column

Fix crash with Variant + AggregateFunction type
This commit is contained in:
Kruglov Pavel 2024-08-05 10:49:22 +00:00 committed by GitHub
commit 2c5687f3a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 98 additions and 1 deletions

View File

@ -330,7 +330,38 @@ ColumnPtr ColumnAggregateFunction::filter(const Filter & filter, ssize_t result_
void ColumnAggregateFunction::expand(const Filter & mask, bool inverted)
{
expandDataByMask<char *>(data, mask, inverted);
ensureOwnership();
Arena & arena = createOrGetArena();
if (mask.size() < data.size())
throw Exception(ErrorCodes::LOGICAL_ERROR, "Mask size should be no less than data size.");
ssize_t from = data.size() - 1;
ssize_t index = mask.size() - 1;
data.resize(mask.size());
while (index >= 0)
{
if (!!mask[index] ^ inverted)
{
if (from < 0)
throw Exception(ErrorCodes::LOGICAL_ERROR, "Too many bytes in mask");
/// Copy only if it makes sense.
if (index != from)
data[index] = data[from];
--from;
}
else
{
data[index] = arena.alignedAlloc(func->sizeOfData(), func->alignOfData());
func->create(data[index]);
}
--index;
}
if (from != -1)
throw Exception(ErrorCodes::LOGICAL_ERROR, "Not enough bytes in mask");
}
ColumnPtr ColumnAggregateFunction::permute(const Permutation & perm, size_t limit) const

View File

@ -0,0 +1,6 @@
500
fail 500
499
fail 500
500 499
fail 500 500

View File

@ -0,0 +1,60 @@
SET allow_experimental_variant_type = 1;
DROP TABLE IF EXISTS source;
CREATE TABLE source
(
Name String,
Value Int64
) ENGINE = MergeTree ORDER BY ();
INSERT INTO source SELECT ['fail', 'success'][number % 2] as Name, number AS Value FROM numbers(1000);
DROP TABLE IF EXISTS test_agg_variant;
CREATE TABLE test_agg_variant
(
Name String,
Value Variant(AggregateFunction(uniqExact, Int64), AggregateFunction(avg, Int64))
)
ENGINE = MergeTree
ORDER BY (Name);
INSERT INTO test_agg_variant
SELECT
Name,
t AS Value
FROM
(
SELECT
Name,
arrayJoin([
uniqExactState(Value)::Variant(AggregateFunction(uniqExact, Int64), AggregateFunction(avg, Int64)),
avgState(Value)::Variant(AggregateFunction(uniqExact, Int64), AggregateFunction(avg, Int64))
]) AS t
FROM source
GROUP BY Name
);
SELECT
Name,
uniqExactMerge(Value.`AggregateFunction(uniqExact, Int64)`) AS Value
FROM test_agg_variant
GROUP BY Name;
SELECT
Name,
avgMerge(Value.`AggregateFunction(avg, Int64)`) AS Value
FROM test_agg_variant
GROUP BY Name;
SELECT
Name,
uniqExactMerge(Value.`AggregateFunction(uniqExact, Int64)`) AS ValueUniq,
avgMerge(Value.`AggregateFunction(avg, Int64)`) AS ValueAvg
FROM test_agg_variant
GROUP BY Name;
DROP TABLE test_agg_variant;
DROP TABLE source;