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 | |
11 | namespace DB |
12 | { |
13 | |
14 | namespace ErrorCodes |
15 | { |
16 | extern const int UNKNOWN_FUNCTION; |
17 | extern const int LOGICAL_ERROR; |
18 | } |
19 | |
20 | |
21 | void 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 | |
42 | FunctionOverloadResolverImplPtr 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 | |
59 | FunctionOverloadResolverPtr FunctionFactory::get( |
60 | const std::string & name, |
61 | const Context & context) const |
62 | { |
63 | return std::make_shared<FunctionOverloadResolverAdaptor>(getImpl(name, context)); |
64 | } |
65 | |
66 | FunctionOverloadResolverImplPtr 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 | |
83 | FunctionOverloadResolverPtr 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 | |
92 | FunctionFactory & FunctionFactory::instance() |
93 | { |
94 | static FunctionFactory ret; |
95 | return ret; |
96 | } |
97 | |
98 | } |
99 | |