Fix crash in GROUPING SETS

This commit is contained in:
Dmitry Novik 2022-01-14 13:18:05 +00:00
parent b27af90202
commit 9ae9048184
4 changed files with 231 additions and 4 deletions

View File

@ -340,8 +340,6 @@ void ExpressionAnalyzer::analyzeAggregation(ActionsDAGPtr & temp_actions)
if (getContext()->getSettingsRef().enable_positional_arguments) if (getContext()->getSettingsRef().enable_positional_arguments)
replaceForPositionalArguments(group_asts[i], select_query, ASTSelectQuery::Expression::GROUP_BY); replaceForPositionalArguments(group_asts[i], select_query, ASTSelectQuery::Expression::GROUP_BY);
getRootActionsNoMakeSet(group_asts[i], true, temp_actions, false);
if (select_query->group_by_with_grouping_sets) if (select_query->group_by_with_grouping_sets)
{ {
ASTs group_elements_ast; ASTs group_elements_ast;
@ -354,6 +352,8 @@ void ExpressionAnalyzer::analyzeAggregation(ActionsDAGPtr & temp_actions)
for (ssize_t j = 0; j < ssize_t(group_elements_ast.size()); ++j) for (ssize_t j = 0; j < ssize_t(group_elements_ast.size()); ++j)
{ {
getRootActionsNoMakeSet(group_elements_ast[j], true, temp_actions, false);
ssize_t group_size = group_elements_ast.size(); ssize_t group_size = group_elements_ast.size();
const auto & column_name = group_elements_ast[j]->getColumnName(); const auto & column_name = group_elements_ast[j]->getColumnName();
const auto * node = temp_actions->tryFindInIndex(column_name); const auto * node = temp_actions->tryFindInIndex(column_name);
@ -366,6 +366,8 @@ void ExpressionAnalyzer::analyzeAggregation(ActionsDAGPtr & temp_actions)
/// Constant expressions have non-null column pointer at this stage. /// Constant expressions have non-null column pointer at this stage.
if (node->column && isColumnConst(*node->column)) if (node->column && isColumnConst(*node->column))
{ {
select_query->group_by_with_constant_keys = true;
/// But don't remove last key column if no aggregate functions, otherwise aggregation will not work. /// But don't remove last key column if no aggregate functions, otherwise aggregation will not work.
if (!aggregate_descriptions.empty() || group_size > 1) if (!aggregate_descriptions.empty() || group_size > 1)
{ {
@ -399,6 +401,8 @@ void ExpressionAnalyzer::analyzeAggregation(ActionsDAGPtr & temp_actions)
} }
else else
{ {
getRootActionsNoMakeSet(group_asts[i], true, temp_actions, false);
const auto & column_name = group_asts[i]->getColumnName(); const auto & column_name = group_asts[i]->getColumnName();
const auto * node = temp_actions->tryFindInIndex(column_name); const auto * node = temp_actions->tryFindInIndex(column_name);
if (!node) if (!node)

View File

@ -2063,12 +2063,15 @@ void InterpreterSelectQuery::initAggregatorParams(
for (const auto & key : aggregation_keys) for (const auto & key : aggregation_keys)
{ {
size_t key_name_pos = current_data_stream_header.getPositionByName(key.name); size_t key_name_pos = current_data_stream_header.getPositionByName(key.name);
keys_set.insert(key_name_pos); if (!keys_set.contains(key_name_pos))
{
keys_set.insert(key_name_pos);
all_keys.push_back(key_name_pos);
}
keys.push_back(key_name_pos); keys.push_back(key_name_pos);
} }
keys_vector.push_back(keys); keys_vector.push_back(keys);
} }
all_keys.assign(keys_set.begin(), keys_set.end());
params_ptr = std::make_unique<Aggregator::Params>( params_ptr = std::make_unique<Aggregator::Params>(
current_data_stream_header, current_data_stream_header,

View File

@ -0,0 +1,156 @@
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
SECOND QUERY:
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
THIRD QUERY:
\N 1 0 0
\N 2 0 0
\N 3 0 0
\N 4 0 0
\N 5 0 0
\N 1 0 0
\N 2 0 0
\N 3 0 0
\N 4 0 0
\N 5 0 0
\N 0 10 10
\N 0 9 9
\N 0 8 8
\N 0 7 7
\N 0 6 6
\N 0 5 5
\N 0 4 4
\N 0 3 3
\N 0 2 2
\N 0 1 1
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0
\N 0 0 0

View File

@ -0,0 +1,64 @@
DROP TABLE IF EXISTS grouping_sets;
CREATE TABLE grouping_sets(fact_1_id Int32, fact_2_id Int32, fact_3_id Int32, fact_4_id Int32, sales_value Int32) ENGINE = Memory;
INSERT INTO grouping_sets
SELECT
number % 2 + 1 AS fact_1_id,
number % 5 + 1 AS fact_2_id,
number % 10 + 1 AS fact_3_id,
number % 10 + 1 AS fact_4_id,
number % 100 AS sales_value
FROM system.numbers limit 1000;
SELECT
fact_3_id,
fact_4_id
FROM grouping_sets
GROUP BY
GROUPING SETS (
('wo\0ldworldwo\0ldworld'),
(fact_3_id, fact_4_id))
ORDER BY
fact_3_id, fact_4_id;
SELECT 'SECOND QUERY:';
SELECT
fact_3_id,
fact_4_id
FROM grouping_sets
GROUP BY
GROUPING SETS (
(fact_1_id, fact_2_id),
((-9223372036854775808, NULL, (tuple(1.), (tuple(1.), 1048576), 65535))),
((tuple(3.4028234663852886e38), (tuple(1024), -2147483647), NULL)),
(fact_3_id, fact_4_id))
ORDER BY
(NULL, ('256', (tuple(NULL), NULL), NULL, NULL), NULL) ASC,
fact_1_id DESC NULLS FIRST,
fact_2_id DESC NULLS FIRST,
fact_4_id ASC;
SELECT 'THIRD QUERY:';
SELECT
extractAllGroups(NULL, 'worldworldworldwo\0ldworldworldworldwo\0ld'),
fact_2_id,
fact_3_id,
fact_4_id
FROM grouping_sets
GROUP BY
GROUPING SETS (
(sales_value),
(fact_1_id, fact_2_id),
('wo\0ldworldwo\0ldworld'),
(fact_3_id, fact_4_id))
ORDER BY
fact_1_id DESC NULLS LAST,
fact_1_id DESC NULLS FIRST,
fact_2_id ASC,
fact_3_id DESC NULLS FIRST,
fact_4_id ASC;
DROP TABLE IF EXISTS grouping_sets;