diff --git a/dbms/src/AggregateFunctions/AggregateFunctionUniq.cpp b/dbms/src/AggregateFunctions/AggregateFunctionUniq.cpp index d6831ce1c43f4d22f287828942c0bfd792dea20f..882cedca1efe0e7a97c5e6818b44fc1fd3d4fa2b 100644 --- a/dbms/src/AggregateFunctions/AggregateFunctionUniq.cpp +++ b/dbms/src/AggregateFunctions/AggregateFunctionUniq.cpp @@ -24,10 +24,10 @@ namespace ErrorCodes namespace { + /** `DataForVariadic` is a data structure that will be used for `uniq` aggregate function of multiple arguments. * It differs, for example, in that it uses a trivial hash function, since `uniq` of many arguments first hashes them out itself. */ - template AggregateFunctionPtr createAggregateFunctionUniq(const std::string & name, const DataTypes & argument_types, const Array & params) { @@ -37,6 +37,8 @@ AggregateFunctionPtr createAggregateFunctionUniq(const std::string & name, const throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); + bool use_exact_hash_function = !isAllArgumentsContiguousInMemory(argument_types); + if (argument_types.size() == 1) { const IDataType & argument_type = *argument_types[0]; @@ -51,25 +53,25 @@ AggregateFunctionPtr createAggregateFunctionUniq(const std::string & name, const return std::make_shared>(); else if (typeid_cast(&argument_type) || typeid_cast(&argument_type)) return std::make_shared>(); - else if (typeid_cast(&argument_type)) - return std::make_shared>(argument_types); else if (typeid_cast(&argument_type)) return std::make_shared>(); - } - 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); + else if (typeid_cast(&argument_type)) + { + if (use_exact_hash_function) + return std::make_shared>(argument_types); + else + return std::make_shared>(argument_types); + } } /// "Variadic" method also works as a fallback generic case for single argument. - return std::make_shared>(argument_types); + if (use_exact_hash_function) + return std::make_shared>(argument_types); + else + return std::make_shared>(argument_types); } -template