dbms: support WITH TOTALS without GROUP BY

This commit is contained in:
Andrey Mironov 2014-08-04 19:25:38 +04:00
parent d9b4c671cd
commit af4c37ea92
8 changed files with 51 additions and 20 deletions

View File

@ -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);

View File

@ -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);
}; };

View File

@ -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;
} }

View File

@ -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);

View File

@ -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;
} }

View File

@ -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

View File

@ -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 : "");

View File

@ -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)
{ {