1#include <Functions/FunctionFactory.h>
2
3#include <Interpreters/Context.h>
4
5#include <Common/Exception.h>
6
7#include <Poco/String.h>
8
9#include <IO/WriteHelpers.h>
10
11namespace DB
12{
13
14namespace ErrorCodes
15{
16 extern const int UNKNOWN_FUNCTION;
17 extern const int LOGICAL_ERROR;
18}
19
20
21void FunctionFactory::registerFunction(const
22 std::string & name,
23 Creator creator,
24 CaseSensitiveness case_sensitiveness)
25{
26 if (!functions.emplace(name, creator).second)
27 throw Exception("FunctionFactory: the function name '" + name + "' is not unique",
28 ErrorCodes::LOGICAL_ERROR);
29
30 String function_name_lowercase = Poco::toLower(name);
31 if (isAlias(name) || isAlias(function_name_lowercase))
32 throw Exception("FunctionFactory: the function name '" + name + "' is already registered as alias",
33 ErrorCodes::LOGICAL_ERROR);
34
35 if (case_sensitiveness == CaseInsensitive
36 && !case_insensitive_functions.emplace(function_name_lowercase, creator).second)
37 throw Exception("FunctionFactory: the case insensitive function name '" + name + "' is not unique",
38 ErrorCodes::LOGICAL_ERROR);
39}
40
41
42FunctionOverloadResolverImplPtr FunctionFactory::getImpl(
43 const std::string & name,
44 const Context & context) const
45{
46 auto res = tryGetImpl(name, context);
47 if (!res)
48 {
49 auto hints = this->getHints(name);
50 if (!hints.empty())
51 throw Exception("Unknown function " + name + ". Maybe you meant: " + toString(hints),
52 ErrorCodes::UNKNOWN_FUNCTION);
53 else
54 throw Exception("Unknown function " + name, ErrorCodes::UNKNOWN_FUNCTION);
55 }
56 return res;
57}
58
59FunctionOverloadResolverPtr FunctionFactory::get(
60 const std::string & name,
61 const Context & context) const
62{
63 return std::make_shared<FunctionOverloadResolverAdaptor>(getImpl(name, context));
64}
65
66FunctionOverloadResolverImplPtr FunctionFactory::tryGetImpl(
67 const std::string & name_param,
68 const Context & context) const
69{
70 String name = getAliasToOrName(name_param);
71
72 auto it = functions.find(name);
73 if (functions.end() != it)
74 return it->second(context);
75
76 it = case_insensitive_functions.find(Poco::toLower(name));
77 if (case_insensitive_functions.end() != it)
78 return it->second(context);
79
80 return {};
81}
82
83FunctionOverloadResolverPtr FunctionFactory::tryGet(
84 const std::string & name,
85 const Context & context) const
86{
87 auto impl = tryGetImpl(name, context);
88 return impl ? std::make_shared<FunctionOverloadResolverAdaptor>(std::move(impl))
89 : nullptr;
90}
91
92FunctionFactory & FunctionFactory::instance()
93{
94 static FunctionFactory ret;
95 return ret;
96}
97
98}
99