forked from alibaba/AliSQL
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuilt_in_functions.cpp
More file actions
171 lines (147 loc) · 6.31 KB
/
built_in_functions.cpp
File metadata and controls
171 lines (147 loc) · 6.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include "duckdb/function/built_in_functions.hpp"
#include "duckdb/catalog/catalog.hpp"
#include "duckdb/catalog/catalog_entry/scalar_function_catalog_entry.hpp"
#include "duckdb/main/extension_entries.hpp"
#include "duckdb/parser/parsed_data/create_aggregate_function_info.hpp"
#include "duckdb/parser/parsed_data/create_collation_info.hpp"
#include "duckdb/parser/parsed_data/create_copy_function_info.hpp"
#include "duckdb/parser/parsed_data/create_pragma_function_info.hpp"
#include "duckdb/parser/parsed_data/create_scalar_function_info.hpp"
#include "duckdb/parser/parsed_data/create_table_function_info.hpp"
#include "duckdb/main/extension_helper.hpp"
#include "duckdb/main/config.hpp"
namespace duckdb {
BuiltinFunctions::BuiltinFunctions(CatalogTransaction transaction, Catalog &catalog)
: transaction(transaction), catalog(catalog) {
}
BuiltinFunctions::~BuiltinFunctions() {
}
void BuiltinFunctions::AddCollation(string name, ScalarFunction function, bool combinable,
bool not_required_for_equality) {
CreateCollationInfo info(std::move(name), std::move(function), combinable, not_required_for_equality);
info.internal = true;
catalog.CreateCollation(transaction, info);
}
void BuiltinFunctions::AddFunction(AggregateFunctionSet set) {
CreateAggregateFunctionInfo info(std::move(set));
info.internal = true;
catalog.CreateFunction(transaction, info);
}
void BuiltinFunctions::AddFunction(AggregateFunction function) {
CreateAggregateFunctionInfo info(std::move(function));
info.internal = true;
catalog.CreateFunction(transaction, info);
}
void BuiltinFunctions::AddFunction(PragmaFunction function) {
CreatePragmaFunctionInfo info(std::move(function));
info.internal = true;
catalog.CreatePragmaFunction(transaction, info);
}
void BuiltinFunctions::AddFunction(const string &name, PragmaFunctionSet functions) {
CreatePragmaFunctionInfo info(name, std::move(functions));
info.internal = true;
catalog.CreatePragmaFunction(transaction, info);
}
void BuiltinFunctions::AddFunction(ScalarFunction function) {
CreateScalarFunctionInfo info(std::move(function));
info.internal = true;
catalog.CreateFunction(transaction, info);
}
void BuiltinFunctions::AddFunction(const vector<string> &names, ScalarFunction function) { // NOLINT: false positive
for (auto &name : names) {
function.name = name;
AddFunction(function);
}
}
void BuiltinFunctions::AddFunction(ScalarFunctionSet set) {
CreateScalarFunctionInfo info(std::move(set));
info.internal = true;
catalog.CreateFunction(transaction, info);
}
void BuiltinFunctions::AddFunction(TableFunction function) {
CreateTableFunctionInfo info(std::move(function));
info.internal = true;
catalog.CreateTableFunction(transaction, info);
}
void BuiltinFunctions::AddFunction(TableFunctionSet set) {
CreateTableFunctionInfo info(std::move(set));
info.internal = true;
catalog.CreateTableFunction(transaction, info);
}
void BuiltinFunctions::AddFunction(CopyFunction function) {
CreateCopyFunctionInfo info(std::move(function));
info.internal = true;
catalog.CreateCopyFunction(transaction, info);
}
struct ExtensionFunctionInfo : public ScalarFunctionInfo {
explicit ExtensionFunctionInfo(string extension_p) : extension(std::move(extension_p)) {
}
string extension;
};
unique_ptr<FunctionData> BindExtensionFunction(ClientContext &context, ScalarFunction &bound_function,
vector<unique_ptr<Expression>> &arguments) {
// if this is triggered we are trying to call a method that is present in an extension
// but the extension is not loaded
// try to autoload the extension
// first figure out which extension we need to auto-load
auto &function_info = bound_function.function_info->Cast<ExtensionFunctionInfo>();
auto &extension_name = function_info.extension;
auto &db = *context.db;
if (!ExtensionHelper::CanAutoloadExtension(extension_name)) {
throw BinderException("Trying to call function \"%s\" which is present in extension \"%s\" - but the extension "
"is not loaded and could not be auto-loaded",
bound_function.name, extension_name);
}
// auto-load the extension
ExtensionHelper::AutoLoadExtension(db, extension_name);
// now find the function in the catalog
auto &catalog = Catalog::GetSystemCatalog(db);
auto &function_entry = catalog.GetEntry<ScalarFunctionCatalogEntry>(context, DEFAULT_SCHEMA, bound_function.name);
// override the function with the extension function
bound_function = function_entry.functions.GetFunctionByArguments(context, bound_function.arguments);
// call the original bind (if any)
if (!bound_function.bind) {
return nullptr;
}
return bound_function.bind(context, bound_function, arguments);
}
void BuiltinFunctions::AddExtensionFunction(ScalarFunctionSet set) {
CreateScalarFunctionInfo info(std::move(set));
info.internal = true;
catalog.CreateFunction(transaction, info);
}
void BuiltinFunctions::RegisterExtensionOverloads() {
#ifdef GENERATE_EXTENSION_ENTRIES
// do not insert auto loading placeholders when generating extension entries
return;
#endif
ScalarFunctionSet current_set;
for (auto &entry : EXTENSION_FUNCTION_OVERLOADS) {
vector<LogicalType> arguments;
auto splits = StringUtil::Split(entry.signature, ">");
auto return_type = DBConfig::ParseLogicalType(splits[1]);
auto parameters = Value(splits[0]).DefaultCastAs(LogicalType::LIST(LogicalType::VARCHAR));
for (auto ¶m : ListValue::GetChildren(parameters)) {
arguments.push_back(DBConfig::ParseLogicalType(param.GetValue<string>()));
}
if (entry.type != CatalogType::SCALAR_FUNCTION_ENTRY) {
throw InternalException(
"Extension function overloads only supported for scalar functions currently - %s has a different type",
entry.name);
}
ScalarFunction function(entry.name, std::move(arguments), std::move(return_type), nullptr,
BindExtensionFunction);
function.function_info = make_shared_ptr<ExtensionFunctionInfo>(entry.extension);
if (current_set.name != entry.name) {
if (!current_set.name.empty()) {
// create set of functions
AddExtensionFunction(current_set);
}
current_set = ScalarFunctionSet(entry.name);
}
// add this function to the set of function overloads
current_set.AddFunction(std::move(function));
}
AddExtensionFunction(std::move(current_set));
}
} // namespace duckdb