From 5c8b01da3a49b53ce94d2f162e6e77e8703961d9 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sat, 24 Sep 2011 20:32:41 +0000 Subject: [PATCH] dbms: development [#CONV-2944]. --- .../DataStreams/AggregatingBlockInputStream.h | 11 +- .../DB/Functions/FunctionsArithmetic.h | 130 ++++++++---------- .../DB/Functions/FunctionsComparison.h | 32 ++--- dbms/include/DB/Functions/FunctionsLogical.h | 44 +++--- dbms/include/DB/Functions/IFunction.h | 6 +- dbms/include/DB/Interpreters/Aggregator.h | 4 + dbms/include/DB/Interpreters/Expression.h | 7 + .../DB/Interpreters/InterpreterSelectQuery.h | 9 +- dbms/include/DB/Parsers/ASTFunction.h | 8 +- .../AggregatingBlockInputStream.cpp | 10 ++ .../Functions/tests/functions_arithmetic.cpp | 18 +-- dbms/src/Interpreters/Aggregator.cpp | 10 ++ dbms/src/Interpreters/Expression.cpp | 109 +++++++++------ dbms/src/Interpreters/tests/expression.cpp | 10 +- 14 files changed, 216 insertions(+), 192 deletions(-) diff --git a/dbms/include/DB/DataStreams/AggregatingBlockInputStream.h b/dbms/include/DB/DataStreams/AggregatingBlockInputStream.h index dc13c37763e..b9170958a2a 100644 --- a/dbms/include/DB/DataStreams/AggregatingBlockInputStream.h +++ b/dbms/include/DB/DataStreams/AggregatingBlockInputStream.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include @@ -19,19 +20,23 @@ class AggregatingBlockInputStream : public IProfilingBlockInputStream { public: AggregatingBlockInputStream(BlockInputStreamPtr input_, const ColumnNumbers & keys_, AggregateDescriptions & aggregates_) - : input(input_), keys(keys_), aggregates(aggregates_), aggregator(keys_, aggregates_), has_been_read(false) + : input(input_), aggregator(keys_, aggregates_), has_been_read(false) { children.push_back(input); } + /** keys берутся из Expression::PART_GROUP + * Агрегатные функции ищутся везде в выражении. + * Столбцы, соответствующие keys и аргументам агрегатных функций, уже должны быть вычислены. + */ +// AggregatingBlockInputStream(BlockInputStreamPtr input_, SharedPtr expression); + Block readImpl(); String getName() const { return "AggregatingBlockInputStream"; } private: BlockInputStreamPtr input; - const ColumnNumbers keys; - AggregateDescriptions aggregates; Aggregator aggregator; bool has_been_read; }; diff --git a/dbms/include/DB/Functions/FunctionsArithmetic.h b/dbms/include/DB/Functions/FunctionsArithmetic.h index c521080f44d..88354feeee8 100644 --- a/dbms/include/DB/Functions/FunctionsArithmetic.h +++ b/dbms/include/DB/Functions/FunctionsArithmetic.h @@ -235,34 +235,34 @@ class FunctionBinaryArithmetic : public IFunction { private: template - bool checkRightType(const DataTypes & arguments, DataTypes & types_res) const + bool checkRightType(const DataTypes & arguments, DataTypePtr & type_res) const { if (dynamic_cast(&*arguments[1])) { - types_res.push_back(new typename DataTypeFromFieldType< - typename Impl::ResultType>::Type); + type_res = new typename DataTypeFromFieldType< + typename Impl::ResultType>::Type; return true; } return false; } template - bool checkLeftType(const DataTypes & arguments, DataTypes & types_res) const + bool checkLeftType(const DataTypes & arguments, DataTypePtr & type_res) const { if (dynamic_cast(&*arguments[0])) { - if ( checkRightType(arguments, types_res) - || checkRightType(arguments, types_res) - || checkRightType(arguments, types_res) - || checkRightType(arguments, types_res) - || checkRightType(arguments, types_res) - || checkRightType(arguments, types_res) - || checkRightType(arguments, types_res) - || checkRightType(arguments, types_res) - || checkRightType(arguments, types_res) - || checkRightType(arguments, types_res) - || checkRightType(arguments, types_res) - || checkRightType(arguments, types_res)) + if ( checkRightType(arguments, type_res) + || checkRightType(arguments, type_res) + || checkRightType(arguments, type_res) + || checkRightType(arguments, type_res) + || checkRightType(arguments, type_res) + || checkRightType(arguments, type_res) + || checkRightType(arguments, type_res) + || checkRightType(arguments, type_res) + || checkRightType(arguments, type_res) + || checkRightType(arguments, type_res) + || checkRightType(arguments, type_res) + || checkRightType(arguments, type_res)) return true; else throw Exception("Illegal type " + arguments[1]->getName() + " of second argument of function " + getName(), @@ -273,14 +273,14 @@ private: template - bool executeRightType(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result, const ColumnVector * col_left) + bool executeRightType(Block & block, const ColumnNumbers & arguments, size_t result, const ColumnVector * col_left) { if (ColumnVector * col_right = dynamic_cast *>(&*block.getByPosition(arguments[1]).column)) { typedef typename Impl::ResultType ResultType; ColumnVector * col_res = new ColumnVector; - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; typename ColumnVector::Container_t & vec_res = col_res->getData(); vec_res.resize(col_left->getData().size()); @@ -293,7 +293,7 @@ private: typedef typename Impl::ResultType ResultType; ColumnVector * col_res = new ColumnVector; - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; typename ColumnVector::Container_t & vec_res = col_res->getData(); vec_res.resize(col_left->getData().size()); @@ -306,14 +306,14 @@ private: } template - bool executeConstRightType(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result, const ColumnConst * col_left) + bool executeConstRightType(Block & block, const ColumnNumbers & arguments, size_t result, const ColumnConst * col_left) { if (ColumnVector * col_right = dynamic_cast *>(&*block.getByPosition(arguments[1]).column)) { typedef typename Impl::ResultType ResultType; ColumnVector * col_res = new ColumnVector; - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; typename ColumnVector::Container_t & vec_res = col_res->getData(); vec_res.resize(col_left->size()); @@ -329,7 +329,7 @@ private: Impl::constant_constant(col_left->getData(), col_right->getData(), res); ColumnConst * col_res = new ColumnConst(col_left->size(), res); - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; return true; } @@ -338,7 +338,7 @@ private: } template - bool executeLeftType(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result) + bool executeLeftType(Block & block, const ColumnNumbers & arguments, size_t result) { if (ColumnVector * col_left = dynamic_cast *>(&*block.getByPosition(arguments[0]).column)) { @@ -388,40 +388,36 @@ public: } /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. - DataTypes getReturnTypes(const DataTypes & arguments) const + DataTypePtr getReturnType(const DataTypes & arguments) const { if (arguments.size() != 2) throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " + Poco::NumberFormatter::format(arguments.size()) + ", should be 2.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); - DataTypes types_res; + DataTypePtr type_res; - if (!( checkLeftType(arguments, types_res) - || checkLeftType(arguments, types_res) - || checkLeftType(arguments, types_res) - || checkLeftType(arguments, types_res) - || checkLeftType(arguments, types_res) - || checkLeftType(arguments, types_res) - || checkLeftType(arguments, types_res) - || checkLeftType(arguments, types_res) - || checkLeftType(arguments, types_res) - || checkLeftType(arguments, types_res) - || checkLeftType(arguments, types_res) - || checkLeftType(arguments, types_res))) + if (!( checkLeftType(arguments, type_res) + || checkLeftType(arguments, type_res) + || checkLeftType(arguments, type_res) + || checkLeftType(arguments, type_res) + || checkLeftType(arguments, type_res) + || checkLeftType(arguments, type_res) + || checkLeftType(arguments, type_res) + || checkLeftType(arguments, type_res) + || checkLeftType(arguments, type_res) + || checkLeftType(arguments, type_res) + || checkLeftType(arguments, type_res) + || checkLeftType(arguments, type_res))) throw Exception("Illegal type " + arguments[0]->getName() + " of first argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); - return types_res; + return type_res; } /// Выполнить функцию над блоком. - void execute(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result) + void execute(Block & block, const ColumnNumbers & arguments, size_t result) { - if (result.size() != 1) - throw Exception("Wrong number of result columns in function " + getName() + ", should be 1.", - ErrorCodes::ILLEGAL_NUMBER_OF_RESULT_COLUMNS); - if (!( executeLeftType(block, arguments, result) || executeLeftType(block, arguments, result) || executeLeftType(block, arguments, result) @@ -444,26 +440,26 @@ class FunctionUnaryArithmetic : public IFunction { private: template - bool checkType(const DataTypes & arguments, DataTypes & types_res) const + bool checkType(const DataTypes & arguments, DataTypePtr result) const { if (dynamic_cast(&*arguments[0])) { - types_res.push_back(new typename DataTypeFromFieldType< - typename Impl::ResultType>::Type); + result = new typename DataTypeFromFieldType< + typename Impl::ResultType>::Type; return true; } return false; } template - bool executeType(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result) + bool executeType(Block & block, const ColumnNumbers & arguments, size_t result) { if (ColumnVector * col = dynamic_cast *>(&*block.getByPosition(arguments[0]).column)) { typedef typename Impl::ResultType ResultType; ColumnVector * col_res = new ColumnVector; - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; typename ColumnVector::Container_t & vec_res = col_res->getData(); vec_res.resize(col->getData().size()); @@ -479,7 +475,7 @@ private: Impl::constant(col->getData(), res); ColumnConst * col_res = new ColumnConst(col->size(), res); - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; return true; } @@ -495,40 +491,36 @@ public: } /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. - DataTypes getReturnTypes(const DataTypes & arguments) const + DataTypePtr getReturnType(const DataTypes & arguments) const { if (arguments.size() != 1) throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " + Poco::NumberFormatter::format(arguments.size()) + ", should be 1.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); - DataTypes types_res; + DataTypePtr result; - if (!( checkType(arguments, types_res) - || checkType(arguments, types_res) - || checkType(arguments, types_res) - || checkType(arguments, types_res) - || checkType(arguments, types_res) - || checkType(arguments, types_res) - || checkType(arguments, types_res) - || checkType(arguments, types_res) - || checkType(arguments, types_res) - || checkType(arguments, types_res) - || checkType(arguments, types_res) - || checkType(arguments, types_res))) + if (!( checkType(arguments, result) + || checkType(arguments, result) + || checkType(arguments, result) + || checkType(arguments, result) + || checkType(arguments, result) + || checkType(arguments, result) + || checkType(arguments, result) + || checkType(arguments, result) + || checkType(arguments, result) + || checkType(arguments, result) + || checkType(arguments, result) + || checkType(arguments, result))) throw Exception("Illegal type " + arguments[0]->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); - return types_res; + return result; } /// Выполнить функцию над блоком. - void execute(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result) + void execute(Block & block, const ColumnNumbers & arguments, size_t result) { - if (result.size() != 1) - throw Exception("Wrong number of result columns in function " + getName() + ", should be 1.", - ErrorCodes::ILLEGAL_NUMBER_OF_RESULT_COLUMNS); - if (!( executeType(block, arguments, result) || executeType(block, arguments, result) || executeType(block, arguments, result) diff --git a/dbms/include/DB/Functions/FunctionsComparison.h b/dbms/include/DB/Functions/FunctionsComparison.h index 8c09358cee8..d38f135f3f5 100644 --- a/dbms/include/DB/Functions/FunctionsComparison.h +++ b/dbms/include/DB/Functions/FunctionsComparison.h @@ -1130,12 +1130,12 @@ class FunctionComparison : public IFunction private: template - bool executeNumRightType(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result, const ColumnVector * col_left) + bool executeNumRightType(Block & block, const ColumnNumbers & arguments, size_t result, const ColumnVector * col_left) { if (ColumnVector * col_right = dynamic_cast *>(&*block.getByPosition(arguments[1]).column)) { ColumnUInt8 * col_res = new ColumnUInt8; - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; ColumnUInt8::Container_t & vec_res = col_res->getData(); vec_res.resize(col_left->getData().size()); @@ -1146,7 +1146,7 @@ private: else if (ColumnConst * col_right = dynamic_cast *>(&*block.getByPosition(arguments[1]).column)) { ColumnUInt8 * col_res = new ColumnUInt8; - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; ColumnUInt8::Container_t & vec_res = col_res->getData(); vec_res.resize(col_left->getData().size()); @@ -1159,12 +1159,12 @@ private: } template - bool executeNumConstRightType(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result, const ColumnConst * col_left) + bool executeNumConstRightType(Block & block, const ColumnNumbers & arguments, size_t result, const ColumnConst * col_left) { if (ColumnVector * col_right = dynamic_cast *>(&*block.getByPosition(arguments[1]).column)) { ColumnUInt8 * col_res = new ColumnUInt8; - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; ColumnUInt8::Container_t & vec_res = col_res->getData(); vec_res.resize(col_left->size()); @@ -1178,7 +1178,7 @@ private: NumImpl::constant_constant(col_left->getData(), col_right->getData(), res); ColumnConstUInt8 * col_res = new ColumnConstUInt8(col_left->size(), res); - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; return true; } @@ -1187,7 +1187,7 @@ private: } template - bool executeNumLeftType(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result) + bool executeNumLeftType(Block & block, const ColumnNumbers & arguments, size_t result) { if (ColumnVector * col_left = dynamic_cast *>(&*block.getByPosition(arguments[0]).column)) { @@ -1229,7 +1229,7 @@ private: return false; } - void executeString(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result) + void executeString(Block & block, const ColumnNumbers & arguments, size_t result) { IColumn * c0 = &*block.getByPosition(arguments[0]).column; IColumn * c1 = &*block.getByPosition(arguments[1]).column; @@ -1244,13 +1244,13 @@ private: if (c0_const && c1_const) { ColumnConstUInt8 * c_res = new ColumnConstUInt8(c0_const->size(), 0); - block.getByPosition(result[0]).column = c_res; + block.getByPosition(result).column = c_res; StringImpl::constant_constant(c0_const->getData(), c1_const->getData(), c_res->getData()); } else { ColumnUInt8 * c_res = new ColumnUInt8; - block.getByPosition(result[0]).column = c_res; + block.getByPosition(result).column = c_res; ColumnUInt8::Container_t & vec_res = c_res->getData(); vec_res.resize(c0->size()); @@ -1311,7 +1311,7 @@ public: } /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. - DataTypes getReturnTypes(const DataTypes & arguments) const + DataTypePtr getReturnType(const DataTypes & arguments) const { if (arguments.size() != 2) throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " @@ -1326,18 +1326,12 @@ public: throw Exception("Illegal types of arguments (" + arguments[0]->getName() + ", " + arguments[1]->getName() + ")" " of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); - DataTypes types_res; - types_res.push_back(new DataTypeUInt8); - return types_res; + return new DataTypeUInt8; } /// Выполнить функцию над блоком. - void execute(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result) + void execute(Block & block, const ColumnNumbers & arguments, size_t result) { - if (result.size() != 1) - throw Exception("Wrong number of result columns in function " + getName() + ", should be 1.", - ErrorCodes::ILLEGAL_NUMBER_OF_RESULT_COLUMNS); - if (block.getByPosition(arguments[0]).column->isNumeric()) { if (!( executeNumLeftType(block, arguments, result) diff --git a/dbms/include/DB/Functions/FunctionsLogical.h b/dbms/include/DB/Functions/FunctionsLogical.h index c228dd1d14f..33fe7032485 100644 --- a/dbms/include/DB/Functions/FunctionsLogical.h +++ b/dbms/include/DB/Functions/FunctionsLogical.h @@ -127,12 +127,12 @@ class FunctionBinaryLogical : public IFunction private: template - bool executeRightType(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result, const ColumnVector * col_left) + bool executeRightType(Block & block, const ColumnNumbers & arguments, size_t result, const ColumnVector * col_left) { if (ColumnVector * col_right = dynamic_cast *>(&*block.getByPosition(arguments[1]).column)) { ColumnVector * col_res = new ColumnVector; - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; typename ColumnVector::Container_t & vec_res = col_res->getData(); vec_res.resize(col_left->getData().size()); @@ -143,7 +143,7 @@ private: else if (ColumnConst * col_right = dynamic_cast *>(&*block.getByPosition(arguments[1]).column)) { ColumnVector * col_res = new ColumnVector; - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; typename ColumnVector::Container_t & vec_res = col_res->getData(); vec_res.resize(col_left->getData().size()); @@ -156,12 +156,12 @@ private: } template - bool executeConstRightType(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result, const ColumnConst * col_left) + bool executeConstRightType(Block & block, const ColumnNumbers & arguments, size_t result, const ColumnConst * col_left) { if (ColumnVector * col_right = dynamic_cast *>(&*block.getByPosition(arguments[1]).column)) { ColumnVector * col_res = new ColumnVector; - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; typename ColumnVector::Container_t & vec_res = col_res->getData(); vec_res.resize(col_left->size()); @@ -175,7 +175,7 @@ private: Impl::constant_constant(col_left->getData(), col_right->getData(), res); ColumnConst * col_res = new ColumnConst(col_left->size(), res); - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; return true; } @@ -184,7 +184,7 @@ private: } template - bool executeLeftType(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result) + bool executeLeftType(Block & block, const ColumnNumbers & arguments, size_t result) { if (ColumnVector * col_left = dynamic_cast *>(&*block.getByPosition(arguments[0]).column)) { @@ -234,7 +234,7 @@ public: } /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. - DataTypes getReturnTypes(const DataTypes & arguments) const + DataTypePtr getReturnType(const DataTypes & arguments) const { if (arguments.size() != 2) throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " @@ -247,18 +247,12 @@ public: + ") of arguments of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); - DataTypes types_res; - types_res.push_back(new DataTypeUInt8); - return types_res; + return new DataTypeUInt8; } /// Выполнить функцию над блоком. - void execute(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result) + void execute(Block & block, const ColumnNumbers & arguments, size_t result) { - if (result.size() != 1) - throw Exception("Wrong number of result columns in function " + getName() + ", should be 1.", - ErrorCodes::ILLEGAL_NUMBER_OF_RESULT_COLUMNS); - if (!( executeLeftType(block, arguments, result) || executeLeftType(block, arguments, result) || executeLeftType(block, arguments, result) @@ -282,12 +276,12 @@ class FunctionUnaryLogical : public IFunction private: template - bool executeType(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result) + bool executeType(Block & block, const ColumnNumbers & arguments, size_t result) { if (ColumnVector * col = dynamic_cast *>(&*block.getByPosition(arguments[0]).column)) { ColumnVector * col_res = new ColumnVector; - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; typename ColumnVector::Container_t & vec_res = col_res->getData(); vec_res.resize(col->getData().size()); @@ -301,7 +295,7 @@ private: Impl::constant(col->getData(), res); ColumnConst * col_res = new ColumnConst(col->size(), res); - block.getByPosition(result[0]).column = col_res; + block.getByPosition(result).column = col_res; return true; } @@ -317,7 +311,7 @@ public: } /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. - DataTypes getReturnTypes(const DataTypes & arguments) const + DataTypePtr getReturnType(const DataTypes & arguments) const { if (arguments.size() != 1) throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " @@ -330,18 +324,12 @@ public: + ") of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); - DataTypes types_res; - types_res.push_back(new DataTypeUInt8); - return types_res; + return new DataTypeUInt8; } /// Выполнить функцию над блоком. - void execute(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result) + void execute(Block & block, const ColumnNumbers & arguments, size_t result) { - if (result.size() != 1) - throw Exception("Wrong number of result columns in function " + getName() + ", should be 1.", - ErrorCodes::ILLEGAL_NUMBER_OF_RESULT_COLUMNS); - if (!( executeType(block, arguments, result) || executeType(block, arguments, result) || executeType(block, arguments, result) diff --git a/dbms/include/DB/Functions/IFunction.h b/dbms/include/DB/Functions/IFunction.h index 0d55934f210..7273ec5506c 100644 --- a/dbms/include/DB/Functions/IFunction.h +++ b/dbms/include/DB/Functions/IFunction.h @@ -30,11 +30,11 @@ public: /// Получить основное имя функции. virtual String getName() const = 0; - /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. - virtual DataTypes getReturnTypes(const DataTypes & arguments) const = 0; + /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. + virtual DataTypePtr getReturnType(const DataTypes & arguments) const = 0; /// Выполнить функцию над блоком. - virtual void execute(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & result) = 0; + virtual void execute(Block & block, const ColumnNumbers & arguments, size_t result) = 0; }; diff --git a/dbms/include/DB/Interpreters/Aggregator.h b/dbms/include/DB/Interpreters/Aggregator.h index 949b03eea50..0f508404615 100644 --- a/dbms/include/DB/Interpreters/Aggregator.h +++ b/dbms/include/DB/Interpreters/Aggregator.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -13,6 +14,7 @@ struct AggregateDescription { AggregateFunctionPtr function; ColumnNumbers arguments; + Names argument_names; /// Используются, если arguments не заданы. }; typedef std::vector AggregateDescriptions; @@ -26,6 +28,7 @@ class Aggregator { public: Aggregator(const ColumnNumbers & keys_, AggregateDescriptions & aggregates_) : keys(keys_), aggregates(aggregates_) {}; + Aggregator(const Names & key_names_, AggregateDescriptions & aggregates_) : key_names(key_names_), aggregates(aggregates_) {}; AggregatedData execute(BlockInputStreamPtr stream); @@ -34,6 +37,7 @@ public: private: ColumnNumbers keys; + Names key_names; AggregateDescriptions aggregates; Block sample; diff --git a/dbms/include/DB/Interpreters/Expression.h b/dbms/include/DB/Interpreters/Expression.h index 3d5a3b237a8..3dc52790ceb 100644 --- a/dbms/include/DB/Interpreters/Expression.h +++ b/dbms/include/DB/Interpreters/Expression.h @@ -6,6 +6,7 @@ #include #include +#include namespace DB @@ -43,6 +44,10 @@ public: */ DataTypes getReturnTypes(); + /** Получить список ключей агрегирования и описаний агрегатных функций, если в запросе есть GROUP BY. + */ + void getAggregateInfo(Names & key_names, AggregateDescriptions & aggregates); + private: ASTPtr ast; const Context & context; @@ -82,6 +87,8 @@ private: void collectFinalColumns(ASTPtr ast, Block & src, Block & dst, bool without_duplicates, unsigned part_id); void getReturnTypesImpl(ASTPtr ast, DataTypes & res); + + void getAggregateInfoImpl(ASTPtr ast, Names & key_names, AggregateDescriptions & aggregates); }; diff --git a/dbms/include/DB/Interpreters/InterpreterSelectQuery.h b/dbms/include/DB/Interpreters/InterpreterSelectQuery.h index e8df769c624..6e6920f1148 100644 --- a/dbms/include/DB/Interpreters/InterpreterSelectQuery.h +++ b/dbms/include/DB/Interpreters/InterpreterSelectQuery.h @@ -32,10 +32,11 @@ private: PART_OTHER = 1, PART_SELECT = 2, PART_WHERE = 4, - PART_HAVING = 8, - PART_ORDER = 16, - PART_BELOW_AGGREGATE_FUNCTIONS = 32, - PART_ABOVE_AGGREGATE_FUNCTIONS = 64, + PART_GROUP = 8, + PART_HAVING = 16, + PART_ORDER = 32, + PART_BELOW_AGGREGATE_FUNCTIONS = 64, + PART_ABOVE_AGGREGATE_FUNCTIONS = 128, }; diff --git a/dbms/include/DB/Parsers/ASTFunction.h b/dbms/include/DB/Parsers/ASTFunction.h index 939e68cdb66..181c3e2fd8e 100644 --- a/dbms/include/DB/Parsers/ASTFunction.h +++ b/dbms/include/DB/Parsers/ASTFunction.h @@ -22,10 +22,10 @@ public: FunctionPtr function; /// или агрегатная функция AggregateFunctionPtr aggregate_function; - /// типы возвращаемых значений - DataTypes return_types; - /// номера столбцов возвращаемых значений - ColumnNumbers return_column_numbers; + /// тип возвращаемого значения + DataTypePtr return_type; + /// номер столбца возвращаемого значения + size_t return_column_number; ASTFunction() {} ASTFunction(StringRange range_) : IAST(range_) {} diff --git a/dbms/src/DataStreams/AggregatingBlockInputStream.cpp b/dbms/src/DataStreams/AggregatingBlockInputStream.cpp index ada83164327..9069e042174 100644 --- a/dbms/src/DataStreams/AggregatingBlockInputStream.cpp +++ b/dbms/src/DataStreams/AggregatingBlockInputStream.cpp @@ -5,6 +5,16 @@ namespace DB { +/*AggregatingBlockInputStream::AggregatingBlockInputStream(BlockInputStreamPtr input_, SharedPtr expression) + : input(input_), has_been_read(false) +{ + children.push_back(input); + + +}*/ + + + Block AggregatingBlockInputStream::readImpl() { if (has_been_read) diff --git a/dbms/src/Functions/tests/functions_arithmetic.cpp b/dbms/src/Functions/tests/functions_arithmetic.cpp index f96f9b3f04d..b276ef59d54 100644 --- a/dbms/src/Functions/tests/functions_arithmetic.cpp +++ b/dbms/src/Functions/tests/functions_arithmetic.cpp @@ -45,25 +45,19 @@ int main(int argc, char ** argv) arg_nums.push_back(0); arg_nums.push_back(1); - DB::ColumnNumbers res_nums; - res_nums.push_back(2); + size_t res_num = 2; - DB::DataTypes res_types = f.getReturnTypes(arg_types); + DB::DataTypePtr res_type = f.getReturnType(arg_types); - for (DB::DataTypes::const_iterator it = res_types.begin(); it != res_types.end(); ++it) - { - DB::ColumnWithNameAndType descr_res; - descr_res.type = *it; - descr_res.name = "z"; - - block.insert(descr_res); - } + DB::ColumnWithNameAndType descr_res; + descr_res.type = res_type; + descr_res.name = "z"; { Poco::Stopwatch stopwatch; stopwatch.start(); - f.execute(block, arg_nums, res_nums); + f.execute(block, arg_nums, res_num); stopwatch.stop(); std::cout << std::fixed << std::setprecision(2) diff --git a/dbms/src/Interpreters/Aggregator.cpp b/dbms/src/Interpreters/Aggregator.cpp index 1469734e29c..a5006afa172 100644 --- a/dbms/src/Interpreters/Aggregator.cpp +++ b/dbms/src/Interpreters/Aggregator.cpp @@ -37,6 +37,16 @@ AggregatedData Aggregator::execute(BlockInputStreamPtr stream) /// Читаем все данные while (Block block = stream->read()) { + /// Преобразуем имена столбцов в номера, если номера не заданы + if (keys.empty() && !key_names.empty()) + for (Names::const_iterator it = key_names.begin(); it != key_names.end(); ++it) + keys.push_back(block.getPositionByName(*it)); + + for (AggregateDescriptions::iterator it = aggregates.begin(); it != aggregates.end(); ++it) + if (it->arguments.empty() && !it->argument_names.empty()) + for (Names::const_iterator jt = it->argument_names.begin(); jt != it->argument_names.end(); ++jt) + it->arguments.push_back(block.getPositionByName(*jt)); + /// Запоминаем столбцы, с которыми будем работать for (size_t i = 0, size = keys_size; i < size; ++i) key_columns[i] = block.getByPosition(keys[i]).column; diff --git a/dbms/src/Interpreters/Expression.cpp b/dbms/src/Interpreters/Expression.cpp index d074952644a..53c809857fa 100644 --- a/dbms/src/Interpreters/Expression.cpp +++ b/dbms/src/Interpreters/Expression.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -13,14 +14,14 @@ namespace DB { -/** Если функция возвращает много аргументов, то в имена всех соответствующих столбцов, - * кроме первого, будем добавлять _1, _2 и т. п. - */ -static std::string functionReturnValueSuffix(size_t i) +static std::string getName(ASTPtr & ast) { - return i == 0 ? "" : ("_" + Poco::NumberFormatter::format(i)); + if (ASTIdentifier * ident = dynamic_cast(&*ast)) + return ident->name; + else + return ast->getTreeID(); } - + void Expression::addSemantic(ASTPtr & ast) { @@ -78,7 +79,7 @@ void Expression::checkTypes(ASTPtr ast) for (ASTs::iterator it = arguments.begin(); it != arguments.end(); ++it) { if (ASTFunction * arg = dynamic_cast(&**it)) - argument_types.insert(argument_types.end(), arg->return_types.begin(), arg->return_types.end()); + argument_types.push_back(arg->return_type); else if (ASTIdentifier * arg = dynamic_cast(&**it)) argument_types.push_back(arg->type); else if (ASTLiteral * arg = dynamic_cast(&**it)) @@ -89,10 +90,10 @@ void Expression::checkTypes(ASTPtr ast) if (node->aggregate_function) { node->aggregate_function->setArguments(argument_types); - node->return_types.push_back(node->aggregate_function->getReturnType()); + node->return_type = node->aggregate_function->getReturnType(); } else - node->return_types = node->function->getReturnTypes(argument_types); + node->return_type = node->function->getReturnType(argument_types); } } @@ -178,33 +179,19 @@ void Expression::executeImpl(ASTPtr ast, Block & block, unsigned part_id) { /// Вставляем в блок столбцы - результаты вычисления функции ColumnNumbers argument_numbers; - ColumnNumbers & result_numbers = node->return_column_numbers; - result_numbers.clear(); - size_t res_num = 0; - for (DataTypes::const_iterator it = node->return_types.begin(); it != node->return_types.end(); ++it) - { - ColumnWithNameAndType column; - column.type = *it; - column.name = node->getTreeID() + functionReturnValueSuffix(res_num); + ColumnWithNameAndType column; + column.type = node->return_type; + column.name = getName(ast); - result_numbers.push_back(block.columns()); - block.insert(column); - ++res_num; - } + size_t result_number = block.columns(); + block.insert(column); ASTs arguments = node->arguments->children; for (ASTs::iterator it = arguments.begin(); it != arguments.end(); ++it) - { - if (ASTIdentifier * ident = dynamic_cast(&**it)) - argument_numbers.push_back(block.getPositionByName(ident->name)); - else if (ASTFunction * func = dynamic_cast(&**it)) - argument_numbers.insert(argument_numbers.end(), func->return_column_numbers.begin(), func->return_column_numbers.end()); - else - argument_numbers.push_back(block.getPositionByName((*it)->getTreeID())); - } + argument_numbers.push_back(block.getPositionByName(getName(*it))); - node->function->execute(block, argument_numbers, result_numbers); + node->function->execute(block, argument_numbers, result_number); } } else if (ASTLiteral * node = dynamic_cast(&*ast)) @@ -212,7 +199,7 @@ void Expression::executeImpl(ASTPtr ast, Block & block, unsigned part_id) ColumnWithNameAndType column; column.column = node->type->createConstColumn(block.rows(), node->value); column.type = node->type; - column.name = node->getTreeID(); + column.name = getName(ast); block.insert(column); } @@ -243,17 +230,10 @@ void Expression::collectFinalColumns(ASTPtr ast, Block & src, Block & dst, bool if (ASTIdentifier * ident = dynamic_cast(&*ast)) { if (ident->kind == ASTIdentifier::Column) - without_duplicates ? dst.insertUnique(src.getByName(ident->name)) : dst.insert(src.getByName(ident->name)); - } - else if (dynamic_cast(&*ast)) - without_duplicates ? dst.insertUnique(src.getByName(ast->getTreeID())) : dst.insert(src.getByName(ast->getTreeID())); - else if (ASTFunction * func = dynamic_cast(&*ast)) - { - for (size_t i = 0, size = func->return_types.size(); i != size; ++i) - without_duplicates - ? dst.insertUnique(src.getByName(ast->getTreeID() + functionReturnValueSuffix(i))) - : dst.insert(src.getByName(ast->getTreeID() + functionReturnValueSuffix(i))); + without_duplicates ? dst.insertUnique(src.getByName(getName(ast))) : dst.insert(src.getByName(getName(ast))); } + else if (dynamic_cast(&*ast) || dynamic_cast(&*ast)) + without_duplicates ? dst.insertUnique(src.getByName(getName(ast))) : dst.insert(src.getByName(getName(ast))); else for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it) collectFinalColumns(*it, src, dst, without_duplicates, part_id); @@ -279,11 +259,56 @@ void Expression::getReturnTypesImpl(ASTPtr ast, DataTypes & res) else if (ASTLiteral * lit = dynamic_cast(&*ast)) res.push_back(lit->type); else if (ASTFunction * func = dynamic_cast(&*ast)) - res.insert(res.end(), func->return_types.begin(), func->return_types.end()); + res.push_back(func->return_type); else for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it) getReturnTypesImpl(*it, res); } + +void Expression::getAggregateInfoImpl(ASTPtr ast, Names & key_names, AggregateDescriptions & aggregates) +{ + /// Обход в глубину + if (ASTSelectQuery * select = dynamic_cast(&*ast)) + { + if (select->group_expression_list) + { + for (ASTs::iterator it = select->group_expression_list->children.begin(); it != select->group_expression_list->children.end(); ++it) + { + if (ASTIdentifier * ident = dynamic_cast(&**it)) + { + if (ident->kind == ASTIdentifier::Column) + key_names.push_back(getName(*it)); + } + else if (dynamic_cast(&**it) || dynamic_cast(&**it)) + key_names.push_back(getName(*it)); + } + } + } + + if (ASTFunction * func = dynamic_cast(&*ast)) + { + if (func->aggregate_function) + { + AggregateDescription desc; + desc.function = func->aggregate_function; + + for (ASTs::iterator it = func->arguments->children.begin(); it != func->arguments->children.end(); ++it) + desc.argument_names.push_back(getName(*it)); + + aggregates.push_back(desc); + } + } + + for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it) + getAggregateInfoImpl(*it, key_names, aggregates); +} + + +void Expression::getAggregateInfo(Names & key_names, AggregateDescriptions & aggregates) +{ + getAggregateInfoImpl(ast, key_names, aggregates); +} + } diff --git a/dbms/src/Interpreters/tests/expression.cpp b/dbms/src/Interpreters/tests/expression.cpp index 2346736c975..6f287468677 100644 --- a/dbms/src/Interpreters/tests/expression.cpp +++ b/dbms/src/Interpreters/tests/expression.cpp @@ -28,14 +28,8 @@ void dump(DB::IAST & ast, int level = 0) if (DB::ASTFunction * node = dynamic_cast(&ast)) { - std::cout << prefix << node << " Function, name = " << node->function->getName() << ", return types: "; - for (DB::DataTypes::const_iterator it = node->return_types.begin(); it != node->return_types.end(); ++it) - { - if (it != node->return_types.begin()) - std::cout << ", "; - std::cout << (*it)->getName(); - } - std::cout << std::endl; + std::cout << prefix << node << " Function, name = " << node->function->getName() + << ", return type: " << node->return_type->getName() << std::endl; } else if (DB::ASTIdentifier * node = dynamic_cast(&ast)) {