From e7f40f25b371cb4587635a9b8938622642620f4f Mon Sep 17 00:00:00 2001 From: Michael Kolupaev Date: Thu, 20 Jun 2013 13:50:55 +0000 Subject: [PATCH] clickhouse: fixed count() in some cases [#CONV-2944]. --- .../DB/Interpreters/ExpressionActions.h | 2 ++ .../DB/Interpreters/ExpressionAnalyzer.h | 4 +++- dbms/src/Interpreters/ExpressionActions.cpp | 4 ++-- dbms/src/Interpreters/ExpressionAnalyzer.cpp | 24 +++++++++++++++++-- .../Interpreters/InterpreterSelectQuery.cpp | 24 ------------------- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/dbms/include/DB/Interpreters/ExpressionActions.h b/dbms/include/DB/Interpreters/ExpressionActions.h index 286a2bc327..59e48766c4 100644 --- a/dbms/include/DB/Interpreters/ExpressionActions.h +++ b/dbms/include/DB/Interpreters/ExpressionActions.h @@ -192,6 +192,8 @@ public: std::string getID() const; std::string dumpActions() const; + + static std::string getSmallestColumn(const NamesAndTypesList & columns); private: NamesAndTypesList input_columns; diff --git a/dbms/include/DB/Interpreters/ExpressionAnalyzer.h b/dbms/include/DB/Interpreters/ExpressionAnalyzer.h index ce4f427008..d4f92e178f 100644 --- a/dbms/include/DB/Interpreters/ExpressionAnalyzer.h +++ b/dbms/include/DB/Interpreters/ExpressionAnalyzer.h @@ -39,7 +39,7 @@ public: /// Получить список ключей агрегирования и описаний агрегатных функций, если в запросе есть GROUP BY. void getAggregateInfo(Names & key_names, AggregateDescriptions & aggregates); - /// Получить набор столбцов, которые достаточно прочесть для выичсления выражения. + /// Получить набор столбцов, которые достаточно прочесть для вычисления выражения. Names getRequiredColumns(); @@ -214,6 +214,8 @@ private: NamesAndTypesList::iterator findColumn(const String & name, NamesAndTypesList & cols); NamesAndTypesList::iterator findColumn(const String & name) { return findColumn(name, columns); } + void removeUnusedColumns(); + /** Создать словарь алиасов. */ void createAliasesDict(ASTPtr & ast); diff --git a/dbms/src/Interpreters/ExpressionActions.cpp b/dbms/src/Interpreters/ExpressionActions.cpp index a896196472..5cece7811a 100644 --- a/dbms/src/Interpreters/ExpressionActions.cpp +++ b/dbms/src/Interpreters/ExpressionActions.cpp @@ -404,7 +404,7 @@ void ExpressionActions::execute(Block & block) const } } -static std::string getAnyColumn(const NamesAndTypesList & columns) +std::string ExpressionActions::getSmallestColumn(const NamesAndTypesList & columns) { NamesAndTypesList::const_iterator it = columns.begin(); @@ -437,7 +437,7 @@ void ExpressionActions::finalize(const Names & output_columns) /// Не будем оставлять блок пустым, чтобы не потерять количество строк в нем. if (final_columns.empty()) - final_columns.insert(getAnyColumn(input_columns)); + final_columns.insert(getSmallestColumn(input_columns)); /// Какие столбцы нужны, чтобы выполнить действия от текущего до последнего. NameSet needed_columns = final_columns; diff --git a/dbms/src/Interpreters/ExpressionAnalyzer.cpp b/dbms/src/Interpreters/ExpressionAnalyzer.cpp index c9225a4995..aa09995dc5 100644 --- a/dbms/src/Interpreters/ExpressionAnalyzer.cpp +++ b/dbms/src/Interpreters/ExpressionAnalyzer.cpp @@ -57,6 +57,8 @@ void ExpressionAnalyzer::init() createAliasesDict(ast); /// Если есть агрегатные функции, присвоит has_aggregation=true. normalizeTree(); + removeUnusedColumns(); + /// Найдем агрегатные функции. if (select_query && (select_query->group_expression_list || select_query->having_expression)) has_aggregation = true; @@ -1008,12 +1010,30 @@ void ExpressionAnalyzer::getAggregateInfo(Names & key_names, AggregateDescriptio aggregates = aggregate_descriptions; } -Names ExpressionAnalyzer::getRequiredColumns() +void ExpressionAnalyzer::removeUnusedColumns() { NamesSet required; NamesSet ignored; getRequiredColumnsImpl(ast, required, ignored); - Names res(required.begin(), required.end()); + + /// Нужно прочитать хоть один столбец, чтобы узнать количество строк. + if (required.empty()) + required.insert(ExpressionActions::getSmallestColumn(columns)); + + for (NamesAndTypesList::iterator it = columns.begin(); it != columns.end();) + { + NamesAndTypesList::iterator it0 = it; + ++it; + if (!required.count(it0->first)) + columns.erase(it0); + } +} + +Names ExpressionAnalyzer::getRequiredColumns() +{ + Names res; + for (NamesAndTypesList::iterator it = columns.begin(); it != columns.end(); ++it) + res.push_back(it->first); return res; } diff --git a/dbms/src/Interpreters/InterpreterSelectQuery.cpp b/dbms/src/Interpreters/InterpreterSelectQuery.cpp index 073321a5da..a326221468 100644 --- a/dbms/src/Interpreters/InterpreterSelectQuery.cpp +++ b/dbms/src/Interpreters/InterpreterSelectQuery.cpp @@ -362,10 +362,6 @@ QueryProcessingStage::Enum InterpreterSelectQuery::executeFetchColumns(BlockInpu + ", maximum: " + Poco::NumberFormatter::format(settings.limits.max_columns_to_read), ErrorCodes::TOO_MUCH_COLUMNS); - /// Если не указан ни один столбец из таблицы, то будем читать первый попавшийся (чтобы хотя бы знать число строк). - if (required_columns.empty()) - required_columns.push_back(getAnyColumn()); - size_t limit_length = 0; size_t limit_offset = 0; getLimitLengthAndOffset(query, limit_length, limit_offset); @@ -645,24 +641,4 @@ BlockInputStreamPtr InterpreterSelectQuery::executeAndFormat(WriteBuffer & buf) } -String InterpreterSelectQuery::getAnyColumn() -{ - NamesAndTypesList::const_iterator it = context.getColumns().begin(); - - size_t min_size = it->second->isNumeric() ? it->second->getSizeOfField() : 100; - String res = it->first; - for (; it != context.getColumns().end(); ++it) - { - size_t current_size = it->second->isNumeric() ? it->second->getSizeOfField() : 100; - if (current_size < min_size) - { - min_size = current_size; - res = it->first; - } - } - - return res; -} - - } -- GitLab