mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-20 14:42:02 +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 normalizeTree();
|
||||||
void normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_asts, SetOfASTs & current_asts, std::string current_alias);
|
void normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_asts, SetOfASTs & current_asts, std::string current_alias);
|
||||||
|
|
||||||
/// Eliminates injective function calls from group by statement
|
/// Eliminates injective function calls and constant expressions from group by statement
|
||||||
void eliminateInjectives();
|
void optimizeGroupBy();
|
||||||
|
|
||||||
/// Превратить перечисление значений или подзапрос в ASTSet. node - функция in или notIn.
|
/// Превратить перечисление значений или подзапрос в ASTSet. node - функция in или notIn.
|
||||||
void makeSet(ASTFunction * node, const Block & sample_block);
|
void makeSet(ASTFunction * node, const Block & sample_block);
|
||||||
|
@ -22,7 +22,7 @@ protected:
|
|||||||
class ParserParenthesisExpression : public IParserBase
|
class ParserParenthesisExpression : public IParserBase
|
||||||
{
|
{
|
||||||
protected:
|
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);
|
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, Expected & expected);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ void ExpressionAnalyzer::init()
|
|||||||
normalizeTree();
|
normalizeTree();
|
||||||
|
|
||||||
/// GROUP BY injective function elimination
|
/// GROUP BY injective function elimination
|
||||||
eliminateInjectives();
|
optimizeGroupBy();
|
||||||
|
|
||||||
/// array_join_alias_to_name, array_join_result_to_source.
|
/// array_join_alias_to_name, array_join_result_to_source.
|
||||||
getArrayJoinedColumns();
|
getArrayJoinedColumns();
|
||||||
@ -122,7 +122,7 @@ void ExpressionAnalyzer::analyzeAggregation()
|
|||||||
if (select_query->group_expression_list)
|
if (select_query->group_expression_list)
|
||||||
{
|
{
|
||||||
NameSet unique_keys;
|
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)
|
for (size_t i = 0; i < group_asts.size(); ++i)
|
||||||
{
|
{
|
||||||
getRootActions(group_asts[i], true, false, temp_actions);
|
getRootActions(group_asts[i], true, false, temp_actions);
|
||||||
@ -135,6 +135,17 @@ void ExpressionAnalyzer::analyzeAggregation()
|
|||||||
|
|
||||||
const auto & col = block.getByName(column_name);
|
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};
|
NameAndTypePair key{column_name, col.type};
|
||||||
aggregation_keys.push_back(key);
|
aggregation_keys.push_back(key);
|
||||||
|
|
||||||
@ -145,6 +156,12 @@ void ExpressionAnalyzer::analyzeAggregation()
|
|||||||
aggregated_columns.push_back(std::move(key));
|
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)
|
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))
|
if (!(select_query && select_query->group_expression_list))
|
||||||
return;
|
return;
|
||||||
@ -469,7 +486,15 @@ void ExpressionAnalyzer::eliminateInjectives()
|
|||||||
std::back_inserter(group_exprs), is_literal
|
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;
|
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)
|
if (has_order_by)
|
||||||
executeOrder(streams);
|
executeOrder(streams);
|
||||||
|
@ -77,7 +77,7 @@ bool ParserParenthesisExpression::parseImpl(Pos & pos, Pos end, ASTPtr & node, E
|
|||||||
/// пустое выражение в скобках недопустимо
|
/// пустое выражение в скобках недопустимо
|
||||||
if (expr_list.children.empty())
|
if (expr_list.children.empty())
|
||||||
{
|
{
|
||||||
expected = "not empty list of expressions in parenthesis";
|
expected = "non-empty parenthesized list of expressions";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,18 +198,18 @@ bool ParserSelectQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Expected &
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
ws.ignore(pos, end);
|
ws.ignore(pos, end);
|
||||||
|
}
|
||||||
|
|
||||||
/// WITH TOTALS
|
/// WITH TOTALS
|
||||||
if (s_with.ignore(pos, end, expected))
|
if (s_with.ignore(pos, end, expected))
|
||||||
{
|
{
|
||||||
ws.ignore(pos, end);
|
ws.ignore(pos, end);
|
||||||
if (!s_totals.ignore(pos, end, expected))
|
if (!s_totals.ignore(pos, end, expected))
|
||||||
return false;
|
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
|
/// HAVING expr
|
||||||
|
@ -194,11 +194,11 @@ void formatAST(const ASTSelectQuery & ast, std::ostream & s, size_t indent, bo
|
|||||||
one_line
|
one_line
|
||||||
? formatAST(*ast.group_expression_list, s, indent, hilite, one_line)
|
? formatAST(*ast.group_expression_list, s, indent, hilite, one_line)
|
||||||
: formatExpressionListMultiline(typeid_cast<const ASTExpressionList &>(*ast.group_expression_list), s, indent, hilite);
|
: 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)
|
if (ast.having_expression)
|
||||||
{
|
{
|
||||||
s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << "HAVING " << (hilite ? hilite_none : "");
|
s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << "HAVING " << (hilite ? hilite_none : "");
|
||||||
|
@ -85,7 +85,9 @@ void TCPHandler::runImpl()
|
|||||||
|
|
||||||
sendHello();
|
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)
|
while (1)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user