diff --git a/src/Interpreters/TreeRewriter.cpp b/src/Interpreters/TreeRewriter.cpp index ac49d79c6ba..585eb6f7065 100644 --- a/src/Interpreters/TreeRewriter.cpp +++ b/src/Interpreters/TreeRewriter.cpp @@ -784,6 +784,36 @@ void collectJoinedColumns(TableJoin & analyzed_join, ASTTableJoin & table_join, } } +void ExpandFromFunctionRecursively(std::shared_ptr group_expression_list, ASTFunction * function) +{ + if (function && !AggregateUtils::isAggregateFunction(*function)) + { + for (auto & col : function->arguments->children) + { + if (col->as()) + group_expression_list->children.push_back(col); + else + ExpandFromFunctionRecursively(group_expression_list, col->as()); + } + } +} + +// Expand GROUP BY ALL by listing all the SELECT-ed columns that are not expressions of the aggregate functions +void ExpandGroupByAll(ASTSelectQuery * select_query) +{ + auto group_expression_list = std::make_shared(); + + for (auto & expr : select_query->select()->children) + { + if (expr->as()) + group_expression_list->children.push_back(expr); + else + ExpandFromFunctionRecursively(group_expression_list, expr->as()); + } + + select_query->setExpression(ASTSelectQuery::Expression::GROUP_BY, group_expression_list); +} + std::vector getAggregates(ASTPtr & query, const ASTSelectQuery & select_query) { @@ -1211,6 +1241,10 @@ TreeRewriterResultPtr TreeRewriter::analyzeSelect( if (!select_query) throw Exception("Select analyze for not select asts.", ErrorCodes::LOGICAL_ERROR); + // expand GROUP BY ALL + if (select_query->group_by_all) + ExpandGroupByAll(select_query); + size_t subquery_depth = select_options.subquery_depth; bool remove_duplicates = select_options.remove_duplicates; diff --git a/src/Parsers/ASTSelectQuery.cpp b/src/Parsers/ASTSelectQuery.cpp index 76849653b4e..7c0249557a0 100644 --- a/src/Parsers/ASTSelectQuery.cpp +++ b/src/Parsers/ASTSelectQuery.cpp @@ -104,6 +104,11 @@ void ASTSelectQuery::formatImpl(const FormatSettings & s, FormatState & state, F } } + if (group_by_all) + { + s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "GROUP BY ALL" << (s.hilite ? hilite_none : ""); + } + if (group_by_with_rollup) s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << (s.one_line ? "" : " ") << "WITH ROLLUP" << (s.hilite ? hilite_none : ""); diff --git a/src/Parsers/ASTSelectQuery.h b/src/Parsers/ASTSelectQuery.h index 5e3af545f12..3db8524c8b6 100644 --- a/src/Parsers/ASTSelectQuery.h +++ b/src/Parsers/ASTSelectQuery.h @@ -82,6 +82,7 @@ public: ASTPtr clone() const override; bool distinct = false; + bool group_by_all = false; bool group_by_with_totals = false; bool group_by_with_rollup = false; bool group_by_with_cube = false; diff --git a/src/Parsers/ParserSelectQuery.cpp b/src/Parsers/ParserSelectQuery.cpp index cf335270734..201cd750af8 100644 --- a/src/Parsers/ParserSelectQuery.cpp +++ b/src/Parsers/ParserSelectQuery.cpp @@ -195,6 +195,8 @@ bool ParserSelectQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) select_query->group_by_with_cube = true; else if (s_grouping_sets.ignore(pos, expected)) select_query->group_by_with_grouping_sets = true; + else if (s_all.ignore(pos, expected)) + select_query->group_by_all = true; if ((select_query->group_by_with_rollup || select_query->group_by_with_cube || select_query->group_by_with_grouping_sets) && !open_bracket.ignore(pos, expected)) @@ -205,7 +207,7 @@ bool ParserSelectQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) if (!grouping_sets_list.parse(pos, group_expression_list, expected)) return false; } - else + else if (!select_query->group_by_all) { if (!exp_list.parse(pos, group_expression_list, expected)) return false; diff --git a/tests/queries/0_stateless/02459_group_by_all.reference b/tests/queries/0_stateless/02459_group_by_all.reference new file mode 100644 index 00000000000..8f682dac77a --- /dev/null +++ b/tests/queries/0_stateless/02459_group_by_all.reference @@ -0,0 +1,9 @@ +3 1 +2 2 +1 2 +1 3 1 +1 2 2 +1 1 2 +7 1 +5 2 +3 2 diff --git a/tests/queries/0_stateless/02459_group_by_all.sql b/tests/queries/0_stateless/02459_group_by_all.sql new file mode 100644 index 00000000000..1d0959c994b --- /dev/null +++ b/tests/queries/0_stateless/02459_group_by_all.sql @@ -0,0 +1,14 @@ +DROP TABLE IF EXISTS group_by_all; + +CREATE TABLE group_by_all +( + a int, + b int +) +engine = Memory; + +INSERT INTO group_by_all VALUES (1, 2), (1, 2), (2, 4), (2, 5), (3, 5); + +SELECT a, COUNT(b) FROM group_by_all GROUP BY ALL; +SELECT 1, a, COUNT(b) FROM group_by_all GROUP BY ALL; +SELECT (a * 2) + 1, COUNT(b) FROM group_by_all GROUP BY ALL;