dbms: removing duplicate elements from ORDER BY [#METR-2944].

This commit is contained in:
Alexey Milovidov 2015-03-12 06:31:15 +03:00
parent ed0bb6f3da
commit db2956eb73
5 changed files with 42 additions and 5 deletions

View File

@ -218,6 +218,9 @@ private:
/// Eliminates injective function calls and constant expressions from group by statement
void optimizeGroupBy();
/// Удалить из ORDER BY повторяющиеся элементы.
void optimizeOrderBy();
/// Превратить перечисление значений или подзапрос в ASTSet. node - функция in или notIn.
void makeSet(ASTFunction * node, const Block & sample_block);

View File

@ -85,6 +85,9 @@ void ExpressionAnalyzer::init()
/// GROUP BY injective function elimination.
optimizeGroupBy();
/// Удалить из ORDER BY повторяющиеся элементы.
optimizeOrderBy();
/// array_join_alias_to_name, array_join_result_to_source.
getArrayJoinedColumns();
@ -531,6 +534,38 @@ void ExpressionAnalyzer::optimizeGroupBy()
}
void ExpressionAnalyzer::optimizeOrderBy()
{
if (!(select_query && select_query->order_expression_list))
return;
/// Уникализируем условия сортировки.
using NameAndLocale = std::pair<std::string, std::string>;
std::set<NameAndLocale> elems_set;
ASTs & elems = select_query->order_expression_list->children;
ASTs unique_elems;
unique_elems.reserve(elems.size());
for (const auto & elem : elems)
{
String name = elem->children.front()->getColumnName();
const ASTOrderByElement & order_by_elem = typeid_cast<const ASTOrderByElement &>(*elem);
if (elems_set.emplace(
std::piecewise_construct,
std::forward_as_tuple(name),
std::forward_as_tuple(order_by_elem.collator ? order_by_elem.collator->getLocale() : std::string())).second)
{
unique_elems.emplace_back(elem);
}
}
if (unique_elems.size() < elems.size())
elems = unique_elems;
}
void ExpressionAnalyzer::makeSetsForIndex()
{
if (storage && ast && storage->supportsIndexForIn())

View File

@ -817,12 +817,10 @@ static SortDescription getSortDescription(ASTSelectQuery & query)
{
SortDescription order_descr;
order_descr.reserve(query.order_expression_list->children.size());
for (ASTs::iterator it = query.order_expression_list->children.begin();
it != query.order_expression_list->children.end();
++it)
for (const auto & elem : query.order_expression_list->children)
{
String name = (*it)->children.front()->getColumnName();
const ASTOrderByElement & order_by_elem = typeid_cast<const ASTOrderByElement &>(**it);
String name = elem->children.front()->getColumnName();
const ASTOrderByElement & order_by_elem = typeid_cast<const ASTOrderByElement &>(*elem);
order_descr.emplace_back(name, order_by_elem.direction, order_by_elem.collator);
}

View File

@ -0,0 +1 @@
SELECT n FROM (SELECT number AS n FROM system.numbers LIMIT 1000000) ORDER BY n, n, n, n, n, n, n, n, n, n LIMIT 1000000, 1;