diff --git a/.travis.yml b/.travis.yml index 6dab6f478ab..7af12080396 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ matrix: # apt: # sources: # - ubuntu-toolchain-r-test -# packages: [ g++-7, libicu-dev, libreadline-dev, libmysqlclient-dev, unixodbc-dev, libltdl-dev, libssl-dev, libboost-dev, zlib1g-dev, libdouble-conversion-dev, libzookeeper-mt-dev, libsparsehash-dev, librdkafka-dev, libcapnp-dev, libsparsehash-dev, libgoogle-perftools-dev, bash, expect, python, python-lxml, python-termcolor, curl, perl, sudo ] +# packages: [ g++-7, libicu-dev, libreadline-dev, libmysqlclient-dev, unixodbc-dev, libltdl-dev, libssl-dev, libboost-dev, zlib1g-dev, libdouble-conversion-dev, libzookeeper-mt-dev, libsparsehash-dev, librdkafka-dev, libcapnp-dev, libsparsehash-dev, libgoogle-perftools-dev, bash, expect, python, python-lxml, python-termcolor, curl, perl, sudo, openssl ] # # env: # - MATRIX_EVAL="export CC=gcc-7 && export CXX=g++-7" @@ -36,7 +36,7 @@ matrix: sources: - ubuntu-toolchain-r-test - llvm-toolchain-trusty-5.0 - packages: [ g++-7, clang-5.0, lld-5.0, libicu-dev, libreadline-dev, libmysqlclient-dev, unixodbc-dev, libltdl-dev, libssl-dev, libboost-dev, zlib1g-dev, libdouble-conversion-dev, libzookeeper-mt-dev, libsparsehash-dev, librdkafka-dev, libcapnp-dev, libsparsehash-dev, libgoogle-perftools-dev, bash, expect, python, python-lxml, python-termcolor, curl, perl, sudo ] + packages: [ g++-7, clang-5.0, lld-5.0, libicu-dev, libreadline-dev, libmysqlclient-dev, unixodbc-dev, libltdl-dev, libssl-dev, libboost-dev, zlib1g-dev, libdouble-conversion-dev, libzookeeper-mt-dev, libsparsehash-dev, librdkafka-dev, libcapnp-dev, libsparsehash-dev, libgoogle-perftools-dev, bash, expect, python, python-lxml, python-termcolor, curl, perl, sudo, openssl] env: - MATRIX_EVAL="export CC=clang-5.0 && export CXX=clang++-5.0" diff --git a/CHANGELOG.md b/CHANGELOG.md index 847d0506427..fdb7f5303b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,31 @@ -# ClickHouse 1.1.54356 Release Candidate, 2018-03-06 +# ClickHouse 1.1.54370 Release Candidate, 2018-03-16 + +## New features: + +* Added the `system.macros` table and auto updating of macros when the config file is changed. +* Added the `SYSTEM RELOAD CONFIG` query. +* Added the `maxIntersections(left_col, right_col)` aggregate function, which returns the maximum number of simultaneously intersecting intervals `[left; right]`. The `maxIntersectionsPosition(left, right)` function returns the beginning of the "maximum" interval. ([Michael Furmur](https://github.com/yandex/ClickHouse/pull/2012)). + +## Improvements: + +* When inserting data in a `Replicated` table, fewer requests are made to `ZooKeeper` (and most of the user-level errors have disappeared from the `ZooKeeper` log). +* Added the ability to create aliases for sets. Example: `WITH (1, 2, 3) AS set SELECT number IN set FROM system.numbers LIMIT 10`. + +## Bug fixes: + +* Fixed the `Illegal PREWHERE` error when reading from `Merge` tables over `Distributed` tables. +* Added fixes that allow you to run `clickhouse-server` in IPv4-only Docker containers. +* Fixed a race condition when reading from system `system.parts_columns` tables. +* Removed double buffering during a synchronous insert to a `Distributed` table, which could have caused the connection to timeout. +* Fixed a bug that caused excessively long waits for an unavailable replica before beginning a `SELECT` query. +* Fixed incorrect dates in the `system.parts` table. +* Fixed a bug that made it impossible to insert data in a `Replicated` table if `chroot` was non-empty in the configuration of the `ZooKeeper` cluster. +* Fixed the vertical merging algorithm for an empty `ORDER BY` table. +* Restored the ability to use dictionaries in queries to remote tables, even if these dictionaries are not present on the requestor server. This functionality was lost in release 1.1.54362. +* Restored the behavior for queries like `SELECT * FROM remote('server2', default.table) WHERE col IN (SELECT col2 FROM default.table)` when the right side argument of the `IN` should use a remote `default.table` instead of a local one. This behavior was broken in version 1.1.54358. +* Removed extraneous error-level logging of `Not found column ... in block`. + +# ClickHouse release 1.1.54356, 2018-03-06 ## New features: diff --git a/CHANGELOG_RU.md b/CHANGELOG_RU.md index 2dfbdccb7a4..4e0b481e718 100644 --- a/CHANGELOG_RU.md +++ b/CHANGELOG_RU.md @@ -1,4 +1,32 @@ -# ClickHouse 1.1.54362 Release Candidate, 2018-03-11 +# ClickHouse 1.1.54370 Release Candidate, 2018-03-16 + +## Новые возможности: + +* Добавлена системная таблица `system.macros` и автоматическое обновление макросов при изменении конфигурационного файла. +* Добавлен запрос `SYSTEM RELOAD CONFIG`. +* Добавлена агрегатная функция `maxIntersections(left_col, right_col)`, возвращающая максимальное количество одновременно пересекающихся интервалов `[left; right]`. Функция `maxIntersectionsPosition(left, right)` возвращает начало такого "максимального" интервала. ([Michael Furmur](https://github.com/yandex/ClickHouse/pull/2012)). + +## Улучшения: + +* При вставке данных в `Replicated`-таблицу делается меньше обращений к `ZooKeeper` (также из лога `ZooKeeper` исчезло большинство user-level ошибок). +* Добавлена возможность создавать алиасы для множеств. Пример: `WITH (1, 2, 3) AS set SELECT number IN set FROM system.numbers LIMIT 10`. + +## Исправление ошибок: + +* Исправлена ошибка `Illegal PREWHERE` при чтении из Merge-таблицы над `Distributed`-таблицами. +* Добавлены исправления, позволяющие запускать clickhouse-server в IPv4-only docker-контейнерах. +* Исправлен race condition при чтении из системной таблицы `system.parts_columns` +* Убрана двойная буферизация при синхронной вставке в `Distributed`-таблицу, которая могла приводить к timeout-ам соединений. +* Исправлена ошибка, вызывающая чрезмерно долгое ожидание недоступной реплики перед началом выполнения `SELECT`. +* Исправлено некорректное отображение дат в таблице `system.parts`. +* Исправлена ошибка, приводящая к невозможности вставить данные в `Replicated`-таблицу, если в конфигурации кластера `ZooKeeper` задан непустой `chroot`. +* Исправлен алгоритм вертикального мержа при пустом ключе `ORDER BY` таблицы. +* Возвращена возможность использовать словари в запросах к удаленным таблицам, даже если этих словарей нет на сервере-инициаторе. Данная функциональность была потеряна в версии 1.1.54362. +* Восстановлено поведение, при котором в запросах типа `SELECT * FROM remote('server2', default.table) WHERE col IN (SELECT col2 FROM default.table)` в правой части `IN` должна использоваться удаленная таблица `default.table`, а не локальная. данное поведение было нарушено в версии 1.1.54358. +* Устранено ненужное Error-level логирование `Not found column ... in block`. + + +# Релиз ClickHouse 1.1.54362, 2018-03-11 ## Новые возможности: diff --git a/cmake/find_poco.cmake b/cmake/find_poco.cmake index 9051d63ae47..315e27b798f 100644 --- a/cmake/find_poco.cmake +++ b/cmake/find_poco.cmake @@ -49,7 +49,8 @@ elseif (NOT MISSING_INTERNAL_POCO_LIBRARY) set (Poco_DataODBC_INCLUDE_DIRS "${ClickHouse_SOURCE_DIR}/contrib/poco/Data/ODBC/include/") endif () - if (OPENSSL_FOUND) + # TODO! fix internal ssl + if (OPENSSL_FOUND AND NOT USE_INTERNAL_SSL_LIBRARY) set (Poco_NetSSL_FOUND 1) set (Poco_NetSSL_LIBRARY PocoNetSSL) set (Poco_Crypto_LIBRARY PocoCrypto) diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index e74e9a5b7db..9015f7e7d36 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -100,13 +100,17 @@ if (USE_INTERNAL_RDKAFKA_LIBRARY) mark_as_advanced (ZLIB_INCLUDE_DIR) if (USE_INTERNAL_SSL_LIBRARY) - add_library(bundled-ssl ALIAS ${OPENSSL_SSL_LIBRARY}) - set (WITH_BUNDLED_SSL 1) + if (MAKE_STATIC_LIBRARIES) + add_library(bundled-ssl ALIAS ${OPENSSL_SSL_LIBRARY}) + set (WITH_BUNDLED_SSL 1 CACHE INTERNAL "") + else () + set (WITH_SSL 0 CACHE INTERNAL "") + endif () endif () add_subdirectory (librdkafka) - if (USE_INTERNAL_SSL_LIBRARY) + if (USE_INTERNAL_SSL_LIBRARY AND MAKE_STATIC_LIBRARIES) target_include_directories(rdkafka PRIVATE BEFORE ${OPENSSL_INCLUDE_DIR}) endif () target_include_directories(rdkafka PRIVATE BEFORE ${ZLIB_INCLUDE_DIR}) @@ -127,16 +131,18 @@ endif () if (USE_INTERNAL_POCO_LIBRARY) - set (ALLOW_DUPLICATE_CUSTOM_TARGETS 1) set (save_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) set (save_CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) set (_save ${ENABLE_TESTS}) set (ENABLE_TESTS 0) set (CMAKE_DISABLE_FIND_PACKAGE_ZLIB 1) if (USE_INTERNAL_SSL_LIBRARY) - set (DISABLE_INTERNAL_OPENSSL 1) - set (ENABLE_NETSSL 0) # TODO! - set (ENABLE_CRYPTO 0) # TODO! + set (DISABLE_INTERNAL_OPENSSL 1 CACHE INTERNAL "") + set (ENABLE_NETSSL 0 CACHE INTERNAL "") # TODO! + set (ENABLE_CRYPTO 0 CACHE INTERNAL "") # TODO! + endif () + if (MSVC) + set (ENABLE_DATA_ODBC 0 CACHE INTERNAL "") # TODO (build fail) endif () add_subdirectory (poco) unset (CMAKE_DISABLE_FIND_PACKAGE_ZLIB) diff --git a/contrib/boost b/contrib/boost index eb5943711e8..5121cc9d037 160000 --- a/contrib/boost +++ b/contrib/boost @@ -1 +1 @@ -Subproject commit eb5943711e88d1008583e6ae3720a5489313d02e +Subproject commit 5121cc9d0375c7b81b24b6087a51684e6cd62ded diff --git a/contrib/libcityhash/src/config.h b/contrib/libcityhash/src/config.h index c873732dd87..61c75fca818 100644 --- a/contrib/libcityhash/src/config.h +++ b/contrib/libcityhash/src/config.h @@ -5,7 +5,11 @@ /* #undef AC_APPLE_UNIVERSAL_BUILD */ /* Define to 1 if the compiler supports __builtin_expect. */ +#if _MSC_VER +#define HAVE_BUILTIN_EXPECT 0 +#else #define HAVE_BUILTIN_EXPECT 1 +#endif /* Define to 1 if you have the header file. */ #define HAVE_DLFCN_H 1 diff --git a/contrib/libfarmhash/CMakeLists.txt b/contrib/libfarmhash/CMakeLists.txt index 7781028094d..16471da3f2f 100644 --- a/contrib/libfarmhash/CMakeLists.txt +++ b/contrib/libfarmhash/CMakeLists.txt @@ -2,4 +2,8 @@ add_library(farmhash farmhash.cc farmhash.h) +if (MSVC) + target_compile_definitions (farmhash PRIVATE FARMHASH_NO_BUILTIN_EXPECT=1) +endif () + target_include_directories (farmhash PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/contrib/libtcmalloc/src/config.h b/contrib/libtcmalloc/src/config.h index 3338309073d..9f9a7a259e5 100644 --- a/contrib/libtcmalloc/src/config.h +++ b/contrib/libtcmalloc/src/config.h @@ -13,7 +13,11 @@ /* #undef ENABLE_SIZED_DELETE */ /* Define to 1 if compiler supports __builtin_expect */ +#if _MSC_VER +#define HAVE_BUILTIN_EXPECT 0 +#else #define HAVE_BUILTIN_EXPECT 1 +#endif /* Define to 1 if compiler supports __builtin_stack_pointer */ /* #undef HAVE_BUILTIN_STACK_POINTER */ diff --git a/dbms/CMakeLists.txt b/dbms/CMakeLists.txt index 965b9b2bfe1..d740ce5a45c 100644 --- a/dbms/CMakeLists.txt +++ b/dbms/CMakeLists.txt @@ -131,7 +131,6 @@ target_link_libraries (clickhouse_common_io ${LINK_LIBRARIES_ONLY_ON_X86_64} ${LZ4_LIBRARY} ${ZSTD_LIBRARY} - ${ZOOKEEPER_LIBRARY} ${DOUBLE_CONVERSION_LIBRARIES} ${Poco_Net_LIBRARY} ${Poco_Data_LIBRARY} @@ -158,10 +157,6 @@ if (NOT USE_INTERNAL_RE2_LIBRARY) target_include_directories (dbms BEFORE PRIVATE ${RE2_INCLUDE_DIR}) endif () -if (NOT USE_INTERNAL_ZOOKEEPER_LIBRARY) - target_include_directories (clickhouse_common_io BEFORE PUBLIC ${ZOOKEEPER_INCLUDE_DIR}) -endif () - if (NOT USE_INTERNAL_BOOST_LIBRARY) target_include_directories (clickhouse_common_io BEFORE PUBLIC ${Boost_INCLUDE_DIRS}) endif () diff --git a/dbms/cmake/version.cmake b/dbms/cmake/version.cmake index b82d8afccbb..990c638bf46 100644 --- a/dbms/cmake/version.cmake +++ b/dbms/cmake/version.cmake @@ -1,6 +1,6 @@ # This strings autochanged from release_lib.sh: -set(VERSION_DESCRIBE v1.1.54363-testing) -set(VERSION_REVISION 54363) +set(VERSION_DESCRIBE v1.1.54371-testing) +set(VERSION_REVISION 54371) # end of autochange set (VERSION_MAJOR 1) diff --git a/dbms/src/AggregateFunctions/AggregateFunctionFactory.cpp b/dbms/src/AggregateFunctions/AggregateFunctionFactory.cpp index 5fc341b3095..eca854a031b 100644 --- a/dbms/src/AggregateFunctions/AggregateFunctionFactory.cpp +++ b/dbms/src/AggregateFunctions/AggregateFunctionFactory.cpp @@ -70,7 +70,10 @@ AggregateFunctionPtr AggregateFunctionFactory::get( return combinator->transformAggregateFunction(nested_function, argument_types, parameters); } - return getImpl(name, argument_types, parameters, recursion_level); + auto res = getImpl(name, argument_types, parameters, recursion_level); + if (!res) + throw Exception("Logical error: AggregateFunctionFactory returned nullptr", ErrorCodes::LOGICAL_ERROR); + return res; } diff --git a/dbms/src/AggregateFunctions/AggregateFunctionMaxIntersections.cpp b/dbms/src/AggregateFunctions/AggregateFunctionMaxIntersections.cpp new file mode 100644 index 00000000000..9f63d399fe7 --- /dev/null +++ b/dbms/src/AggregateFunctions/AggregateFunctionMaxIntersections.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include + + +namespace DB +{ + +namespace +{ + AggregateFunctionPtr createAggregateFunctionMaxIntersections( + AggregateFunctionIntersectionsKind kind, + const std::string & name, const DataTypes & argument_types, const Array & parameters) + { + assertBinary(name, argument_types); + assertNoParameters(name, parameters); + + AggregateFunctionPtr res(createWithNumericType(*argument_types[0], kind, argument_types)); + if (!res) + throw Exception("Illegal types " + argument_types[0]->getName() + " and " + argument_types[1]->getName() + + " of argument for aggregate function " + name, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + + return res; + } +} + +void registerAggregateFunctionsMaxIntersections(AggregateFunctionFactory & factory) +{ + factory.registerFunction("maxIntersections", [](const std::string & name, const DataTypes & argument_types, const Array & parameters) + { return createAggregateFunctionMaxIntersections(AggregateFunctionIntersectionsKind::Count, name, argument_types, parameters); }); + + factory.registerFunction("maxIntersectionsPosition", [](const std::string & name, const DataTypes & argument_types, const Array & parameters) + { return createAggregateFunctionMaxIntersections(AggregateFunctionIntersectionsKind::Position, name, argument_types, parameters); }); +} + +} diff --git a/dbms/src/AggregateFunctions/AggregateFunctionMaxIntersections.h b/dbms/src/AggregateFunctions/AggregateFunctionMaxIntersections.h new file mode 100644 index 00000000000..11ec01e52e4 --- /dev/null +++ b/dbms/src/AggregateFunctions/AggregateFunctionMaxIntersections.h @@ -0,0 +1,170 @@ +#pragma once + +#include + +#include +#include + +#include +#include + +#include +#include + +#include + +#define AGGREGATE_FUNCTION_MAX_INTERSECTIONS_MAX_ARRAY_SIZE 0xFFFFFF + + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int ILLEGAL_TYPE_OF_ARGUMENT; + extern const int TOO_LARGE_ARRAY_SIZE; +} + + +/** maxIntersections: returns maximum count of the intersected intervals defined by start_column and end_column values, + * maxIntersectionsPosition: returns leftmost position of maximum intersection of intervals. + */ + +/// Similar to GroupArrayNumericData. +template +struct MaxIntersectionsData +{ + /// Left or right end of the interval and signed weight; with positive sign for begin of interval and negative sign for end of interval. + using Value = std::pair; + + // Switch to ordinary Allocator after 4096 bytes to avoid fragmentation and trash in Arena + using Allocator = MixedArenaAllocator<4096>; + using Array = PODArray; + + Array value; +}; + +enum class AggregateFunctionIntersectionsKind +{ + Count, + Position +}; + +template +class AggregateFunctionIntersectionsMax final + : public IAggregateFunctionDataHelper, AggregateFunctionIntersectionsMax> +{ +private: + AggregateFunctionIntersectionsKind kind; + +public: + AggregateFunctionIntersectionsMax(AggregateFunctionIntersectionsKind kind_, const DataTypes & arguments) + : kind(kind_) + { + if (!arguments[0]->isNumber()) + throw Exception{getName() + ": first argument must be represented by integer", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT}; + + if (!arguments[1]->isNumber()) + throw Exception{getName() + ": second argument must be represented by integer", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT}; + + if (!arguments[0]->equals(*arguments[1])) + throw Exception{getName() + ": arguments must have the same type", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT}; + } + + String getName() const override + { + return kind == AggregateFunctionIntersectionsKind::Count + ? "maxIntersections" + : "maxIntersectionsPosition"; + } + + DataTypePtr getReturnType() const override + { + if (kind == AggregateFunctionIntersectionsKind::Count) + return std::make_shared(); + else + return std::make_shared>(); + } + + void add(AggregateDataPtr place, const IColumn ** columns, size_t row_num, Arena * arena) const override + { + PointType left = static_cast &>(*columns[0]).getData()[row_num]; + PointType right = static_cast &>(*columns[1]).getData()[row_num]; + + if (!isNaN(left)) + this->data(place).value.push_back(std::make_pair(left, Int64(1)), arena); + + if (!isNaN(right)) + this->data(place).value.push_back(std::make_pair(right, Int64(-1)), arena); + } + + void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override + { + auto & cur_elems = this->data(place); + auto & rhs_elems = this->data(rhs); + + cur_elems.value.insert(rhs_elems.value.begin(), rhs_elems.value.end(), arena); + } + + void serialize(ConstAggregateDataPtr place, WriteBuffer & buf) const override + { + const auto & value = this->data(place).value; + size_t size = value.size(); + writeVarUInt(size, buf); + buf.write(reinterpret_cast(&value[0]), size * sizeof(value[0])); + } + + void deserialize(AggregateDataPtr place, ReadBuffer & buf, Arena * arena) const override + { + size_t size = 0; + readVarUInt(size, buf); + + if (unlikely(size > AGGREGATE_FUNCTION_MAX_INTERSECTIONS_MAX_ARRAY_SIZE)) + throw Exception("Too large array size", ErrorCodes::TOO_LARGE_ARRAY_SIZE); + + auto & value = this->data(place).value; + + value.resize(size, arena); + buf.read(reinterpret_cast(&value[0]), size * sizeof(value[0])); + } + + void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const override + { + Int64 current_intersections = 0; + Int64 max_intersections = 0; + PointType position_of_max_intersections = 0; + + /// const_cast because we will sort the array + auto & array = const_cast::Array &>(this->data(place).value); + + std::sort(array.begin(), array.end(), [](const auto & a, const auto & b) { return a.first < b.first; }); + + for (const auto & point_weight : array) + { + current_intersections += point_weight.second; + if (current_intersections > max_intersections) + { + max_intersections = current_intersections; + position_of_max_intersections = point_weight.first; + } + } + + if (kind == AggregateFunctionIntersectionsKind::Count) + { + auto & result_column = static_cast(to).getData(); + result_column.push_back(max_intersections); + } + else + { + auto & result_column = static_cast &>(to).getData(); + result_column.push_back(position_of_max_intersections); + } + } + + const char * getHeaderFilePath() const override + { + return __FILE__; + } +}; + +} diff --git a/dbms/src/AggregateFunctions/AggregateFunctionSumMap.cpp b/dbms/src/AggregateFunctions/AggregateFunctionSumMap.cpp index 9aedeaabe24..7cad7c35092 100644 --- a/dbms/src/AggregateFunctions/AggregateFunctionSumMap.cpp +++ b/dbms/src/AggregateFunctions/AggregateFunctionSumMap.cpp @@ -37,7 +37,11 @@ AggregateFunctionPtr createAggregateFunctionSumMap(const std::string & name, con values_types.push_back(array_type->getNestedType()); } - return AggregateFunctionPtr(createWithNumericType(*keys_type, keys_type, std::move(values_types))); + AggregateFunctionPtr res(createWithNumericType(*keys_type, keys_type, std::move(values_types))); + if (!res) + throw Exception("Illegal type of argument for aggregate function " + name, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + + return res; } } diff --git a/dbms/src/AggregateFunctions/AggregateFunctionUniq.cpp b/dbms/src/AggregateFunctions/AggregateFunctionUniq.cpp index e64247796af..d6831ce1c43 100644 --- a/dbms/src/AggregateFunctions/AggregateFunctionUniq.cpp +++ b/dbms/src/AggregateFunctions/AggregateFunctionUniq.cpp @@ -33,6 +33,10 @@ AggregateFunctionPtr createAggregateFunctionUniq(const std::string & name, const { assertNoParameters(name, params); + if (argument_types.empty()) + throw Exception("Incorrect number of arguments for aggregate function " + name, + ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); + if (argument_types.size() == 1) { const IDataType & argument_type = *argument_types[0]; @@ -51,23 +55,18 @@ AggregateFunctionPtr createAggregateFunctionUniq(const std::string & name, const return std::make_shared>(argument_types); else if (typeid_cast(&argument_type)) return std::make_shared>(); - else - throw Exception("Illegal type " + argument_types[0]->getName() + " of argument for aggregate function " + name, - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); } - else if (argument_types.size() > 1) + else { /// If there are several arguments, then no tuples allowed among them. for (const auto & type : argument_types) if (typeid_cast(type.get())) throw Exception("Tuple argument of function " + name + " must be the only argument", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); - - return std::make_shared>(argument_types); } - else - throw Exception("Incorrect number of arguments for aggregate function " + name, - ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); + + /// "Variadic" method also works as a fallback generic case for single argument. + return std::make_shared>(argument_types); } template