ClickHouse/src/Functions/FunctionFactory.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

154 lines
4.3 KiB
C++
Raw Normal View History

#include <Functions/FunctionFactory.h>
#include <Interpreters/Context.h>
#include <Common/Exception.h>
2021-01-22 09:02:58 +00:00
#include <Common/CurrentThread.h>
#include <Poco/String.h>
#include <IO/WriteHelpers.h>
#include <AggregateFunctions/AggregateFunctionFactory.h>
2021-01-22 09:02:58 +00:00
namespace DB
{
2016-01-12 02:21:15 +00:00
namespace ErrorCodes
{
extern const int UNKNOWN_FUNCTION;
extern const int LOGICAL_ERROR;
2016-01-12 02:21:15 +00:00
}
2021-02-14 11:09:36 +00:00
const String & getFunctionCanonicalNameIfAny(const String & name)
{
return FunctionFactory::instance().getCanonicalNameIfAny(name);
}
2017-08-14 04:23:38 +00:00
2021-07-03 21:47:43 +00:00
void FunctionFactory::registerFunction(
const std::string & name,
2022-08-27 20:06:03 +00:00
FunctionCreator creator,
FunctionDocumentation doc,
CaseSensitiveness case_sensitiveness)
{
2022-08-27 20:06:03 +00:00
if (!functions.emplace(name, FunctionFactoryData{creator, doc}).second)
throw Exception(ErrorCodes::LOGICAL_ERROR, "FunctionFactory: the function name '{}' is not unique", name);
2017-08-14 04:23:38 +00:00
String function_name_lowercase = Poco::toLower(name);
if (isAlias(name) || isAlias(function_name_lowercase))
throw Exception(ErrorCodes::LOGICAL_ERROR, "FunctionFactory: the function name '{}' is already registered as alias",
name);
2021-02-14 11:09:36 +00:00
if (case_sensitiveness == CaseInsensitive)
{
2022-08-27 20:06:03 +00:00
if (!case_insensitive_functions.emplace(function_name_lowercase, FunctionFactoryData{creator, doc}).second)
throw Exception(ErrorCodes::LOGICAL_ERROR, "FunctionFactory: the case insensitive function name '{}' is not unique",
name);
2021-02-14 11:09:36 +00:00
case_insensitive_name_mapping[function_name_lowercase] = name;
}
}
2021-05-15 17:33:15 +00:00
FunctionOverloadResolverPtr FunctionFactory::getImpl(
Squashed commit of the following: commit e712f469a55ff34ad34b482b15cc4153b7ad7233 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:59:13 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 2a002823084e3a79bffcc17d479620a68eb0644b Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:58:30 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 9e06f407c8ee781ed8ddf98bdfcc31846bf2a0fe Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:55:14 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 9581620f1e839f456fa7894aa1f996d5162ac6cd Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:54:22 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 2a8564c68cb6cc3649fafaf401256d43c9a2e777 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:47:34 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit cf60632d78ec656be3304ef4565e859bb6ce80ba Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:40:09 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit ee3d1dc6e0c4ca60e3ac1e0c30d4b3ed1e66eca0 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:22:49 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 65592ef7116a90104fcd524b53ef8b7cf22640f2 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:18:17 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 37972c257320d3b7e7b294e0fdeffff218647bfd Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:17:06 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit dd909d149974ce5bed2456de1261aa5a368fd3ff Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:16:28 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 3cf43266ca7e30adf01212b1a739ba5fe43639fd Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:15:42 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 6731a3df96d1609286e2536b6432916af7743f0f Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:13:35 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 1b5727e0d56415b7add4cb76110105358663602c Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:11:18 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit bbcf726a55685b8e72f5b40ba0bf1904bd1c0407 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:09:04 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit c03b477d5e2e65014e8906ecfa2efb67ee295af1 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:06:30 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 2986e2fb0466bc18d73693dcdded28fccc0dc66b Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:05:44 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit 5d6cdef13d2e02bd5c4954983334e9162ab2635b Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:04:53 2017 +0300 Less dependencies [#CLICKHOUSE-2] commit f2b819b25ce8b2ccdcb201eefb03e1e6f5aab590 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Jan 14 11:01:47 2017 +0300 Less dependencies [#CLICKHOUSE-2]
2017-01-14 09:00:19 +00:00
const std::string & name,
ContextPtr context) const
{
2019-12-09 14:41:55 +00:00
auto res = tryGetImpl(name, context);
if (!res)
{
String extra_info;
if (AggregateFunctionFactory::instance().hasNameOrAlias(name))
extra_info = ". There is an aggregate function with the same name, but ordinary function is expected here";
auto hints = this->getHints(name);
if (!hints.empty())
throw Exception(ErrorCodes::UNKNOWN_FUNCTION, "Unknown function {}{}. Maybe you meant: {}", name, extra_info, toString(hints));
else
throw Exception(ErrorCodes::UNKNOWN_FUNCTION, "Unknown function {}{}", name, extra_info);
}
return res;
}
2020-05-11 21:21:40 +00:00
std::vector<std::string> FunctionFactory::getAllNames() const
{
2020-05-11 21:18:50 +00:00
std::vector<std::string> res;
res.reserve(functions.size());
2020-05-11 21:21:40 +00:00
for (const auto & func : functions)
2020-05-11 21:18:50 +00:00
res.emplace_back(func.first);
return res;
}
2019-12-09 14:41:55 +00:00
FunctionOverloadResolverPtr FunctionFactory::get(
const std::string & name,
ContextPtr context) const
2019-12-09 14:41:55 +00:00
{
2021-05-15 17:33:15 +00:00
return getImpl(name, context);
2019-12-09 14:41:55 +00:00
}
bool FunctionFactory::has(const std::string & name) const
{
String canonical_name = getAliasToOrName(name);
if (functions.contains(canonical_name))
return true;
canonical_name = Poco::toLower(canonical_name);
return case_insensitive_functions.contains(canonical_name);
}
2021-05-15 17:33:15 +00:00
FunctionOverloadResolverPtr FunctionFactory::tryGetImpl(
const std::string & name_param,
ContextPtr context) const
{
String name = getAliasToOrName(name_param);
2021-05-15 17:33:15 +00:00
FunctionOverloadResolverPtr res;
auto it = functions.find(name);
if (functions.end() != it)
2022-08-27 20:06:03 +00:00
res = it->second.first(context);
else
{
2021-01-28 09:22:01 +00:00
name = Poco::toLower(name);
it = case_insensitive_functions.find(name);
if (case_insensitive_functions.end() != it)
2022-08-27 20:06:03 +00:00
res = it->second.first(context);
}
if (!res)
return nullptr;
if (CurrentThread::isInitialized())
{
auto query_context = CurrentThread::get().getQueryContext();
if (query_context && query_context->getSettingsRef().log_queries)
query_context->addQueryFactoriesInfo(Context::QueryLogFactories::Function, name);
}
return res;
}
2019-12-09 14:41:55 +00:00
FunctionOverloadResolverPtr FunctionFactory::tryGet(
const std::string & name,
ContextPtr context) const
2019-12-09 14:41:55 +00:00
{
auto impl = tryGetImpl(name, context);
2021-05-15 17:33:15 +00:00
return impl ? std::move(impl) : nullptr;
2019-12-09 14:41:55 +00:00
}
FunctionFactory & FunctionFactory::instance()
{
static FunctionFactory ret;
return ret;
}
FunctionDocumentation FunctionFactory::getDocumentation(const std::string & name) const
2022-08-27 20:06:03 +00:00
{
auto it = functions.find(name);
if (it == functions.end())
throw Exception(ErrorCodes::UNKNOWN_FUNCTION, "Unknown function {}", name);
return it->second.second;
}
}