2017-04-01 09:19:00 +00:00
|
|
|
#include <AggregateFunctions/AggregateFunctionFactory.h>
|
2017-12-24 06:50:11 +00:00
|
|
|
#include <AggregateFunctions/AggregateFunctionCombinatorFactory.h>
|
2017-08-18 17:06:22 +00:00
|
|
|
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <DataTypes/DataTypeAggregateFunction.h>
|
|
|
|
#include <DataTypes/DataTypeArray.h>
|
|
|
|
#include <DataTypes/DataTypeNullable.h>
|
2017-12-20 07:36:30 +00:00
|
|
|
#include <DataTypes/DataTypesNumber.h>
|
2017-08-18 17:06:22 +00:00
|
|
|
#include <IO/WriteBuffer.h>
|
|
|
|
#include <IO/WriteHelpers.h>
|
|
|
|
#include <Interpreters/Context.h>
|
|
|
|
|
2018-01-15 19:07:47 +00:00
|
|
|
#include <Common/StringUtils/StringUtils.h>
|
2017-07-13 16:49:09 +00:00
|
|
|
#include <Common/typeid_cast.h>
|
2016-07-12 13:02:52 +00:00
|
|
|
|
2017-08-18 17:06:22 +00:00
|
|
|
#include <Poco/String.h>
|
|
|
|
|
2011-09-19 03:40:05 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2016-01-12 02:21:15 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
extern const int UNKNOWN_AGGREGATE_FUNCTION;
|
|
|
|
extern const int LOGICAL_ERROR;
|
2016-01-12 02:21:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-14 05:22:09 +00:00
|
|
|
void AggregateFunctionFactory::registerFunction(const String & name, Creator creator, CaseSensitiveness case_sensitiveness)
|
2011-09-19 03:40:05 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
if (creator == nullptr)
|
|
|
|
throw Exception("AggregateFunctionFactory: the aggregate function " + name + " has been provided "
|
|
|
|
" a null constructor", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
if (!aggregate_functions.emplace(name, creator).second)
|
2017-06-10 09:04:31 +00:00
|
|
|
throw Exception("AggregateFunctionFactory: the aggregate function name '" + name + "' is not unique",
|
2017-04-01 07:20:54 +00:00
|
|
|
ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
if (case_sensitiveness == CaseInsensitive
|
|
|
|
&& !case_insensitive_aggregate_functions.emplace(Poco::toLower(name), creator).second)
|
2017-06-10 09:04:31 +00:00
|
|
|
throw Exception("AggregateFunctionFactory: the case insensitive aggregate function name '" + name + "' is not unique",
|
2017-04-01 07:20:54 +00:00
|
|
|
ErrorCodes::LOGICAL_ERROR);
|
2015-09-24 12:40:36 +00:00
|
|
|
}
|
2015-05-17 17:46:21 +00:00
|
|
|
|
|
|
|
|
2017-07-10 23:30:17 +00:00
|
|
|
AggregateFunctionPtr AggregateFunctionFactory::get(
|
|
|
|
const String & name,
|
|
|
|
const DataTypes & argument_types,
|
|
|
|
const Array & parameters,
|
|
|
|
int recursion_level) const
|
2016-07-12 13:02:52 +00:00
|
|
|
{
|
2017-12-24 06:50:11 +00:00
|
|
|
/// If one of types is Nullable, we apply aggregate function combinator "Null".
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-12-24 06:50:11 +00:00
|
|
|
if (std::any_of(argument_types.begin(), argument_types.end(),
|
|
|
|
[](const auto & type) { return type->isNullable(); }))
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-12-24 06:50:11 +00:00
|
|
|
AggregateFunctionCombinatorPtr combinator = AggregateFunctionCombinatorFactory::instance().tryFindSuffix("Null");
|
|
|
|
if (!combinator)
|
|
|
|
throw Exception("Logical error: cannot find aggregate function combinator to apply a function to Nullable arguments.", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
DataTypes nested_types = combinator->transformArguments(argument_types);
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-12-08 05:09:08 +00:00
|
|
|
AggregateFunctionPtr nested_function;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-12-24 06:50:11 +00:00
|
|
|
/// A little hack - if we have NULL arguments, don't even create nested function.
|
|
|
|
/// Combinator will check if nested_function was created.
|
|
|
|
if (name == "count" || std::none_of(argument_types.begin(), argument_types.end(),
|
|
|
|
[](const auto & type) { return type->onlyNull(); }))
|
|
|
|
nested_function = getImpl(name, nested_types, parameters, recursion_level);
|
|
|
|
|
|
|
|
return combinator->transformAggregateFunction(nested_function, argument_types, parameters);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2017-12-24 06:50:11 +00:00
|
|
|
|
|
|
|
return getImpl(name, argument_types, parameters, recursion_level);
|
2016-07-12 13:02:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-10 23:30:17 +00:00
|
|
|
AggregateFunctionPtr AggregateFunctionFactory::getImpl(
|
|
|
|
const String & name,
|
|
|
|
const DataTypes & argument_types,
|
|
|
|
const Array & parameters,
|
|
|
|
int recursion_level) const
|
2015-09-24 12:40:36 +00:00
|
|
|
{
|
2017-12-24 06:50:11 +00:00
|
|
|
/// Find by exact match.
|
2017-04-01 07:20:54 +00:00
|
|
|
auto it = aggregate_functions.find(name);
|
|
|
|
if (it != aggregate_functions.end())
|
2017-12-24 06:50:11 +00:00
|
|
|
return it->second(name, argument_types, parameters);
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-12-24 06:50:11 +00:00
|
|
|
/// Find by case-insensitive name.
|
2017-12-20 07:36:30 +00:00
|
|
|
/// Combinators cannot apply for case insensitive (SQL-style) aggregate function names. Only for native names.
|
2017-04-01 07:20:54 +00:00
|
|
|
if (recursion_level == 0)
|
|
|
|
{
|
|
|
|
auto it = case_insensitive_aggregate_functions.find(Poco::toLower(name));
|
|
|
|
if (it != case_insensitive_aggregate_functions.end())
|
2017-07-10 23:30:17 +00:00
|
|
|
return it->second(name, argument_types, parameters);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
|
2017-12-20 07:36:30 +00:00
|
|
|
/// Combinators of aggregate functions.
|
|
|
|
/// For every aggregate function 'agg' and combiner '-Comb' there is combined aggregate function with name 'aggComb',
|
|
|
|
/// that can have different number and/or types of arguments, different result type and different behaviour.
|
|
|
|
|
2017-12-24 06:50:11 +00:00
|
|
|
if (AggregateFunctionCombinatorPtr combinator = AggregateFunctionCombinatorFactory::instance().tryFindSuffix(name))
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-12-24 06:50:11 +00:00
|
|
|
if (combinator->getName() == "Null")
|
|
|
|
throw Exception("Aggregate function combinator 'Null' is only for internal usage", ErrorCodes::UNKNOWN_AGGREGATE_FUNCTION);
|
2017-12-20 07:36:30 +00:00
|
|
|
|
2017-12-24 06:50:11 +00:00
|
|
|
String nested_name = name.substr(0, name.size() - combinator->getName().size());
|
|
|
|
DataTypes nested_types = combinator->transformArguments(argument_types);
|
|
|
|
AggregateFunctionPtr nested_function = getImpl(nested_name, nested_types, parameters, recursion_level + 1);
|
|
|
|
return combinator->transformAggregateFunction(nested_function, argument_types, parameters);
|
2017-07-10 23:30:17 +00:00
|
|
|
}
|
2017-04-09 12:26:41 +00:00
|
|
|
|
2017-07-10 23:30:17 +00:00
|
|
|
throw Exception("Unknown aggregate function " + name, ErrorCodes::UNKNOWN_AGGREGATE_FUNCTION);
|
2011-09-25 05:07:47 +00:00
|
|
|
}
|
2011-09-19 03:40:05 +00:00
|
|
|
|
2011-09-25 05:07:47 +00:00
|
|
|
|
2017-07-10 23:30:17 +00:00
|
|
|
AggregateFunctionPtr AggregateFunctionFactory::tryGet(const String & name, const DataTypes & argument_types, const Array & parameters) const
|
2011-09-19 03:40:05 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
return isAggregateFunctionName(name)
|
2017-07-10 23:30:17 +00:00
|
|
|
? get(name, argument_types, parameters)
|
2017-04-01 07:20:54 +00:00
|
|
|
: nullptr;
|
2013-05-24 10:49:19 +00:00
|
|
|
}
|
|
|
|
|
2015-04-24 15:49:30 +00:00
|
|
|
|
|
|
|
bool AggregateFunctionFactory::isAggregateFunctionName(const String & name, int recursion_level) const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
if (aggregate_functions.count(name))
|
|
|
|
return true;
|
2016-07-14 05:22:09 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
if (recursion_level == 0 && case_insensitive_aggregate_functions.count(Poco::toLower(name)))
|
|
|
|
return true;
|
2016-07-14 05:22:09 +00:00
|
|
|
|
2017-12-24 06:50:11 +00:00
|
|
|
if (AggregateFunctionCombinatorPtr combinator = AggregateFunctionCombinatorFactory::instance().tryFindSuffix(name))
|
|
|
|
return isAggregateFunctionName(name.substr(0, name.size() - combinator->getName().size()), recursion_level + 1);
|
2017-04-09 12:26:41 +00:00
|
|
|
|
2017-07-10 23:30:17 +00:00
|
|
|
return false;
|
2015-09-24 12:40:36 +00:00
|
|
|
}
|
|
|
|
|
2011-09-19 03:40:05 +00:00
|
|
|
}
|