1+ #pragma once
2+
3+ #include " duckdb.hpp"
4+
5+ #include " spatial/common.hpp"
6+ #include " duckdb/function/function_set.hpp"
7+ #include " duckdb/function/scalar_function.hpp"
8+ #include " duckdb/parser/parsed_data/create_function_info.hpp"
9+
10+ namespace spatial {
11+
12+ namespace core {
13+ // ------------------------------------------------------------------------------
14+ // Scalar Function Variant Builder
15+ // ------------------------------------------------------------------------------
16+
17+ class ScalarFunctionVariantBuilder {
18+ friend class ScalarFunctionBuilder ;
19+
20+ public:
21+ void AddParameter (const char *name, const LogicalType &type);
22+ void SetReturnType (LogicalType type);
23+ void SetFunction (scalar_function_t fn);
24+ void SetInit (init_local_state_t init);
25+ void SetBind (bind_scalar_function_t bind);
26+ void SetDescription (const string &desc);
27+ void SetExample (const string &ex);
28+
29+ private:
30+ explicit ScalarFunctionVariantBuilder () : function({}, LogicalTypeId::INVALID, nullptr ) {
31+ }
32+
33+ ScalarFunction function;
34+ FunctionDescription description = {};
35+ };
36+
37+ inline void ScalarFunctionVariantBuilder::AddParameter (const char *name, const LogicalType &type) {
38+ function.arguments .emplace_back (type);
39+ description.parameter_names .emplace_back (name);
40+ description.parameter_types .emplace_back (type);
41+ }
42+
43+ inline void ScalarFunctionVariantBuilder::SetReturnType (LogicalType type) {
44+ function.return_type = std::move (type);
45+ }
46+
47+ inline void ScalarFunctionVariantBuilder::SetFunction (scalar_function_t fn) {
48+ function.function = fn;
49+ }
50+
51+ inline void ScalarFunctionVariantBuilder::SetInit (init_local_state_t init) {
52+ function.init_local_state = init;
53+ }
54+
55+ inline void ScalarFunctionVariantBuilder::SetBind (bind_scalar_function_t bind) {
56+ function.bind = bind;
57+ }
58+
59+ inline void ScalarFunctionVariantBuilder::SetDescription (const string &desc) {
60+ description.description = desc;
61+ }
62+
63+ inline void ScalarFunctionVariantBuilder::SetExample (const string &ex) {
64+ description.examples .emplace_back (ex);
65+ }
66+
67+ // ------------------------------------------------------------------------------
68+ // Scalar Function Builder
69+ // ------------------------------------------------------------------------------
70+
71+ class ScalarFunctionBuilder {
72+ friend class FunctionBuilder ;
73+
74+ public:
75+ template <class CALLBACK >
76+ void AddVariant (CALLBACK &&callback);
77+ void SetTag (const string &key, const string &value);
78+ void SetDescription (const string &desc);
79+
80+ private:
81+ explicit ScalarFunctionBuilder (const char *name) : set(name) {
82+ }
83+
84+ ScalarFunctionSet set;
85+ vector<FunctionDescription> descriptions = {};
86+ unordered_map<string, string> tags = {};
87+
88+ // If not set by a variant
89+ string default_description;
90+ };
91+
92+ inline void ScalarFunctionBuilder::SetDescription (const string &desc) {
93+ default_description = desc;
94+ }
95+
96+ inline void ScalarFunctionBuilder::SetTag (const string &key, const string &value) {
97+ tags[key] = value;
98+ }
99+
100+ template <class CALLBACK >
101+ void ScalarFunctionBuilder::AddVariant (CALLBACK &&callback) {
102+ ScalarFunctionVariantBuilder builder;
103+
104+ callback (builder);
105+
106+ // A return type is required
107+ if (builder.function .return_type .id () == LogicalTypeId::INVALID) {
108+ throw InternalException (" Return type not set in ScalarFunctionBuilder::AddVariant" );
109+ }
110+
111+ // Add the new variant to the set
112+ set.AddFunction (std::move (builder.function ));
113+
114+ // Add the default description if not set by the variant
115+ if (builder.description .description .empty ()) {
116+ builder.description .description = default_description;
117+ }
118+
119+ // Add the description
120+ descriptions.emplace_back (std::move (builder.description ));
121+ }
122+
123+ // ------------------------------------------------------------------------------
124+ // Function Builder
125+ // ------------------------------------------------------------------------------
126+
127+ class FunctionBuilder {
128+ public:
129+ template <class CALLBACK >
130+ static void RegisterScalar (DatabaseInstance &db, const char *name, CALLBACK &&callback);
131+
132+ private:
133+ static void Register (DatabaseInstance &db, const char *name, ScalarFunctionBuilder &builder);
134+ };
135+
136+ template <class CALLBACK >
137+ void FunctionBuilder::RegisterScalar (DatabaseInstance &db, const char *name, CALLBACK &&callback) {
138+ ScalarFunctionBuilder builder (name);
139+ callback (builder);
140+
141+ Register (db, name, builder);
142+ }
143+
144+ } // namespace core
145+
146+ } // namespace spatial
0 commit comments