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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
//! 函数注册收集器:汇聚过程宏通过 `inventory` 提交的注册项,在扩展初始化时统一注册。
//!
//! Registration collector: gathers the entries submitted by the procedural macros through
//! `inventory` and registers them all when the extension is initialised.
use crate::;
use Itertools;
use Connection;
use ;
use HashMap;
use CString;
/// 注册回调的函数指针类型:接收一个 DuckDB 连接,返回可能失败的结果。
///
/// Signature of a registration callback: takes a DuckDB connection and returns a fallible
/// result.
pub type DuckRegisterFn = fn ;
/// 一条待注册项,由 `#[duck_*]` 宏(以及 `duck_sql_macro_files!`)通过
/// `inventory::submit!` 在编译期提交。
///
/// A single registration entry, submitted at compile time by the `#[duck_*]` macros (and by
/// `duck_sql_macro_files!`) through `inventory::submit!`.
// 把 `DuckFunctionItem` 登记进 inventory,使 `register_all_duckfn` 能遍历所有提交项。
//
// Collect `DuckFunctionItem`s so that `register_all_duckfn` can iterate over every submission.
collect!;
/// 注册本扩展收集到的全部 DuckDB 函数(扩展初始化入口)。
///
/// 开跑之前先 best-effort 捕获宿主文件系统入口(`owned-connection` feature 下会打开一条自有长连接
/// 存进进程级静态,供 `duckfn::duck_vfs::with_file_system` / `duckfn::duck_vfs::file_system` 使用):聚合函数这类
/// 回调在调用期拿不到客户端上下文,注册期是唯一窗口;捕获失败只记原因,不影响注册成败。
///
/// Before anything else it captures the host file-system entry point, best-effort (under the
/// `owned-connection` feature it opens an owned long-lived connection and stores it in a
/// process-level static, backing `duckfn::duck_vfs::with_file_system` /
/// `duckfn::duck_vfs::file_system`): callbacks such as aggregates cannot obtain a client context at
/// call time, so registration is the only window. A failed capture is only recorded — it never
/// decides whether registration succeeds.
///
/// 顺序为:先按提交顺序执行所有 `DuckFunctionItem`(标量函数、表函数、cast、SQL 宏、
/// replacement scan、自定义注册等),再分组注册聚合函数集重载,最后分组注册标量函数集
/// 重载。全部跑完后统一把 `create_type = "print"` 收集到的 DDL 打印一次(见
/// [`crate::flush_queued_type_ddl`])—— 入口点在这里,所以一批 `"print"` 类型只有一块提示。
///
/// Registers every DuckDB function collected by this extension (the extension init entry
/// point). It first runs all `DuckFunctionItem`s in submission order (scalar functions,
/// table functions, casts, SQL macros, replacement scans, custom registrations, ...), then
/// registers the aggregate overload sets and finally the scalar overload sets. Once everything has
/// run it flushes the DDL collected by `create_type = "print"` in one go (see
/// [`crate::flush_queued_type_ddl`]) — this is the entry point, so a batch of print-mode types
/// yields a single notice.
///
/// # Errors
///
/// 任一注册步骤失败时立即返回该错误,后续函数不再注册(收集到的 DDL 仍会打印出来)。
///
/// Returns the first error encountered; remaining functions are then left unregistered (the
/// collected DDL is printed either way).
/// [`register_all_duckfn`] 的实际注册流程;收尾(打印 `create_type = "print"` 的 DDL)由调用方负责。
///
/// The actual registration pass; the caller takes care of the flush afterwards.
/// 聚合函数集重载项:`#[duck_aggregate_function(overloads_name = "xxx")]` 时由宏提交。
///
/// Aggregate function-set overload entry, submitted by the macro when
/// `#[duck_aggregate_function(overloads_name = "xxx")]` is used.
///
/// - `name`:函数集名字,同名(overloads_name 相同)的重载会被合并成一个函数集;
/// - `register_fn`:用函数集名字造出本签名的重载句柄,返回类型取各自的 Output,
/// 所以同一函数集里可以有不同返回类型。
///
/// - `name`: the function-set name; overloads sharing the same `overloads_name` are merged
/// into one set.
/// - `register_fn`: builds the overload handle for this signature with the set name; each
/// overload keeps its own output type, so one set may contain different return types.
///
/// `name` 用 `&'static str` 而不是 `String`:`inventory::submit!` 会把值放进
/// `static` 初始化表达式(const 上下文),`String` 在那里无法构造。
///
/// `name` is a `&'static str` rather than `String` because `inventory::submit!` stores the
/// value in a `static` initialiser (const context), where `String` cannot be constructed.
// 把 `DuckAggregateOverloadItem` 登记进 inventory,供分组注册时遍历。
//
// Collect `DuckAggregateOverloadItem`s so that grouped registration can iterate over them.
collect!;
/// 按 `name` 分组注册所有聚合函数集重载。
///
/// 同名(`overloads_name` 相同)的重载会被合并进同一个 `DuckfnAggregateFunctionSetBuilder`,
/// 然后一次性注册到 DuckDB;每个重载保留自己的返回类型。
///
/// Registers every aggregate overload set, grouped by `name`. Overloads sharing the same
/// `overloads_name` are merged into one `DuckfnAggregateFunctionSetBuilder` and registered
/// to DuckDB in one shot, each overload keeping its own return type.
///
/// # Errors
///
/// 注册任一函数集失败时返回对应错误。
///
/// Returns the error of the first function set that fails to register.
/// 标量函数集重载项:`#[duck_scalar_function(overloads_name = "xxx")]` 时由宏提交。
///
/// Scalar function-set overload entry, submitted by the macro when
/// `#[duck_scalar_function(overloads_name = "xxx")]` is used.
///
/// - `name`:函数集名字,同名(overloads_name 相同)的重载会被合并成一个函数集;
/// - `register_fn`:生成本签名的 `ScalarOverloadBuilder`(自带返回类型与参数表)。
///
/// - `name`: the function-set name; overloads sharing the same `overloads_name` are merged
/// into one set.
/// - `register_fn`: produces the `ScalarOverloadBuilder` of this signature (carrying its own
/// return type and parameter list).
///
/// `name` 用 `&'static str` 的原因同上:inventory 的提交需要 const 上下文。
///
/// `name` is a `&'static str` for the same reason as above: inventory submission needs a
/// const context.
// 把 `DuckScalarOverloadItem` 登记进 inventory,供分组注册时遍历。
//
// Collect `DuckScalarOverloadItem`s so that grouped registration can iterate over them.
collect!;
/// 按 `name` 分组注册所有标量函数集重载。
///
/// 同名(`overloads_name` 相同)的重载会被合并进同一个 `ScalarFunctionSetBuilder`,
/// 再一次性注册到 DuckDB。
///
/// Registers every scalar overload set, grouped by `name`. Overloads sharing the same
/// `overloads_name` are merged into one `ScalarFunctionSetBuilder` and registered together.
///
/// # Errors
///
/// 注册任一函数集失败时返回对应错误。
///
/// Returns the error of the first function set that fails to register.