mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-27 01:51:59 +00:00
dbms: support WITH TOTALS without GROUP BY
This commit is contained in:
parent
d9b4c671cd
commit
af4c37ea92
@ -220,8 +220,8 @@ private:
|
||||
void normalizeTree();
|
||||
void normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_asts, SetOfASTs & current_asts, std::string current_alias);
|
||||
|
||||
/// Eliminates injective function calls from group by statement
|
||||
void eliminateInjectives();
|
||||
/// Eliminates injective function calls and constant expressions from group by statement
|
||||
void optimizeGroupBy();
|
||||
|
||||
/// Превратить перечисление значений или подзапрос в ASTSet. node - функция in или notIn.
|
||||
void makeSet(ASTFunction * node, const Block & sample_block);
|
||||
|
@ -22,7 +22,7 @@ protected:
|
||||
class ParserParenthesisExpression : public IParserBase
|
||||
{
|
||||
protected:
|
||||
const char * getName() const { return "expression in parenthesis"; }
|
||||
const char * getName() const { return "parenthesized expression"; }
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, Expected & expected);
|
||||
};
|
||||
|
||||
|
@ -69,7 +69,7 @@ void ExpressionAnalyzer::init()
|
||||
normalizeTree();
|
||||
|
||||
/// GROUP BY injective function elimination
|
||||
eliminateInjectives();
|
||||
optimizeGroupBy();
|
||||
|
||||
/// array_join_alias_to_name, array_join_result_to_source.
|
||||
getArrayJoinedColumns();
|
||||
@ -122,7 +122,7 @@ void ExpressionAnalyzer::analyzeAggregation()
|
||||
if (select_query->group_expression_list)
|
||||
{
|
||||
NameSet unique_keys;
|
||||
const ASTs & group_asts = select_query->group_expression_list->children;
|
||||
auto & group_asts = select_query->group_expression_list->children;
|
||||
for (size_t i = 0; i < group_asts.size(); ++i)
|
||||
{
|
||||
getRootActions(group_asts[i], true, false, temp_actions);
|
||||
@ -135,6 +135,17 @@ void ExpressionAnalyzer::analyzeAggregation()
|
||||
|
||||
const auto & col = block.getByName(column_name);
|
||||
|
||||
/// constant expressions have non-null column pointer at this stage
|
||||
if (const auto is_constexpr = col.column)
|
||||
{
|
||||
if (i < group_asts.size() - 1)
|
||||
group_asts[i] = std::move(group_asts.back());
|
||||
|
||||
group_asts.pop_back();
|
||||
i -= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
NameAndTypePair key{column_name, col.type};
|
||||
aggregation_keys.push_back(key);
|
||||
|
||||
@ -145,6 +156,12 @@ void ExpressionAnalyzer::analyzeAggregation()
|
||||
aggregated_columns.push_back(std::move(key));
|
||||
}
|
||||
}
|
||||
|
||||
if (group_asts.empty())
|
||||
{
|
||||
select_query->group_expression_list = nullptr;
|
||||
has_aggregation = select_query->having_expression || aggregate_descriptions.size();
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aggregate_descriptions.size(); ++i)
|
||||
@ -426,7 +443,7 @@ void ExpressionAnalyzer::normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_as
|
||||
}
|
||||
|
||||
|
||||
void ExpressionAnalyzer::eliminateInjectives()
|
||||
void ExpressionAnalyzer::optimizeGroupBy()
|
||||
{
|
||||
if (!(select_query && select_query->group_expression_list))
|
||||
return;
|
||||
@ -469,7 +486,15 @@ void ExpressionAnalyzer::eliminateInjectives()
|
||||
std::back_inserter(group_exprs), is_literal
|
||||
);
|
||||
}
|
||||
else if (is_literal(group_exprs[i]))
|
||||
{
|
||||
remove_expr_at_index(i);
|
||||
i -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (group_exprs.empty())
|
||||
select_query->group_expression_list = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -346,6 +346,10 @@ BlockInputStreamPtr InterpreterSelectQuery::execute()
|
||||
|
||||
need_second_distinct_pass = streams.size() > 1;
|
||||
}
|
||||
else if (query.group_by_with_totals && !aggregate_final)
|
||||
{
|
||||
executeTotalsAndHaving(streams, false, nullptr, aggregate_overflow_row);
|
||||
}
|
||||
|
||||
if (has_order_by)
|
||||
executeOrder(streams);
|
||||
|
@ -77,7 +77,7 @@ bool ParserParenthesisExpression::parseImpl(Pos & pos, Pos end, ASTPtr & node, E
|
||||
/// пустое выражение в скобках недопустимо
|
||||
if (expr_list.children.empty())
|
||||
{
|
||||
expected = "not empty list of expressions in parenthesis";
|
||||
expected = "non-empty parenthesized list of expressions";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -198,18 +198,18 @@ bool ParserSelectQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Expected &
|
||||
return false;
|
||||
|
||||
ws.ignore(pos, end);
|
||||
}
|
||||
|
||||
/// WITH TOTALS
|
||||
if (s_with.ignore(pos, end, expected))
|
||||
{
|
||||
ws.ignore(pos, end);
|
||||
if (!s_totals.ignore(pos, end, expected))
|
||||
return false;
|
||||
/// WITH TOTALS
|
||||
if (s_with.ignore(pos, end, expected))
|
||||
{
|
||||
ws.ignore(pos, end);
|
||||
if (!s_totals.ignore(pos, end, expected))
|
||||
return false;
|
||||
|
||||
select_query->group_by_with_totals = true;
|
||||
select_query->group_by_with_totals = true;
|
||||
|
||||
ws.ignore(pos, end);
|
||||
}
|
||||
ws.ignore(pos, end);
|
||||
}
|
||||
|
||||
/// HAVING expr
|
||||
|
@ -194,11 +194,11 @@ void formatAST(const ASTSelectQuery & ast, std::ostream & s, size_t indent, bo
|
||||
one_line
|
||||
? formatAST(*ast.group_expression_list, s, indent, hilite, one_line)
|
||||
: formatExpressionListMultiline(typeid_cast<const ASTExpressionList &>(*ast.group_expression_list), s, indent, hilite);
|
||||
|
||||
if (ast.group_by_with_totals)
|
||||
s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << (one_line ? "" : " ") << "WITH TOTALS" << (hilite ? hilite_none : "");
|
||||
}
|
||||
|
||||
if (ast.group_by_with_totals)
|
||||
s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << (one_line ? "" : " ") << "WITH TOTALS" << (hilite ? hilite_none : "");
|
||||
|
||||
if (ast.having_expression)
|
||||
{
|
||||
s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << "HAVING " << (hilite ? hilite_none : "");
|
||||
|
@ -85,7 +85,9 @@ void TCPHandler::runImpl()
|
||||
|
||||
sendHello();
|
||||
|
||||
connection_context.setProgressCallback(boost::bind(&TCPHandler::updateProgress, this, _1, _2));
|
||||
connection_context.setProgressCallback([this] (const size_t rows, const size_t bytes) {
|
||||
return this->updateProgress(rows, bytes);
|
||||
});
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user