@aetherframework/database 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/examples/mysql-test-pressure.js +1530 -0
  2. package/examples/test-direct.js +116 -0
  3. package/examples/transaction_example.js +127 -0
  4. package/package.json +3 -1
  5. package/src/DatabaseManager.js +565 -0
  6. package/src/core/ConnectionManager.js +351 -0
  7. package/src/core/DatabaseFactory.js +188 -0
  8. package/src/core/MongoQueryBuilder.js +576 -0
  9. package/src/core/PluginManager.js +968 -0
  10. package/src/core/QueryBuilder.js +4394 -0
  11. package/src/core/TransactionManager.js +40 -0
  12. package/src/drivers/clickhouse-driver.js +272 -0
  13. package/src/drivers/index.js +273 -0
  14. package/src/drivers/mongodb-driver.js +87 -0
  15. package/src/drivers/mssql-driver.js +117 -0
  16. package/src/drivers/mysql-driver.js +169 -0
  17. package/src/drivers/oracle-driver.js +101 -0
  18. package/src/drivers/postgres-driver.js +234 -0
  19. package/src/drivers/redis-driver.js +52 -0
  20. package/src/drivers/sqlite-driver.js +67 -0
  21. package/src/middleware/connection-pool.js +455 -0
  22. package/src/middleware/performance-monitor.js +652 -0
  23. package/src/middleware/query-cache.js +500 -0
  24. package/src/middleware/query-logger.js +262 -0
  25. package/src/plugins/AuditPlugin.js +447 -0
  26. package/src/plugins/BasePlugin.js +418 -0
  27. package/src/plugins/BatchOperationPlugin.js +165 -0
  28. package/src/plugins/CachePlugin.js +407 -0
  29. package/src/plugins/CtePlugin.js +523 -0
  30. package/src/plugins/DistributedPlugin.js +543 -0
  31. package/src/plugins/EncryptionPlugin.js +211 -0
  32. package/src/plugins/FullTextSearchPlugin.js +164 -0
  33. package/src/plugins/GeospatialPlugin.js +219 -0
  34. package/src/plugins/GraphQLPlugin.js +162 -0
  35. package/src/plugins/HookPlugin.js +211 -0
  36. package/src/plugins/JsonPlugin.js +366 -0
  37. package/src/plugins/OptimisticLockPlugin.js +374 -0
  38. package/src/plugins/PerformancePlugin.js +175 -0
  39. package/src/plugins/ResiliencePlugin.js +114 -0
  40. package/src/plugins/ShardingPlugin.js +227 -0
  41. package/src/plugins/SoftDeletePlugin.js +258 -0
  42. package/src/plugins/SyncPlugin.js +373 -0
  43. package/src/plugins/VersioningPlugin.js +314 -0
  44. package/src/plugins/WindowFunctionPlugin.js +343 -0
  45. package/src/utils/config-loader.js +632 -0
  46. package/src/utils/error-handler.js +724 -0
  47. package/src/utils/migration-runner.js +1066 -0
@@ -0,0 +1,343 @@
1
+ /**
2
+ * @license MIT
3
+ * Copyright (c) 2026-present AetherFramework Contributors.
4
+ * SPDX-License-Identifier: MIT
5
+ * @module @aetherframework/database/plugin/WindowFunctionPlugin
6
+ */
7
+ import { BasePlugin } from "./BasePlugin.js";
8
+
9
+ /**
10
+ * 窗口函数插件 - 提供标准 SQL 窗口函数的链式调用支持
11
+ */
12
+ export class WindowFunctionPlugin extends BasePlugin {
13
+ constructor(queryBuilder) {
14
+ super(queryBuilder);
15
+ this.pluginName = "WindowFunctionPlugin";
16
+ }
17
+
18
+ _registerMethods() {
19
+ // 注册窗口函数方法到 QueryBuilder
20
+ this.queryBuilder.windowFrame = this.windowFrame.bind(this);
21
+ this.queryBuilder.ntile = this.ntile.bind(this);
22
+ this.queryBuilder.partitionBy = this.partitionBy.bind(this);
23
+ this.queryBuilder.over = this.over.bind(this);
24
+ this.queryBuilder.rowNumber = this.rowNumber.bind(this);
25
+ this.queryBuilder.rank = this.rank.bind(this);
26
+ this.queryBuilder.denseRank = this.denseRank.bind(this);
27
+ this.queryBuilder.lead = this.lead.bind(this);
28
+ this.queryBuilder.lag = this.lag.bind(this);
29
+ this.queryBuilder.firstValue = this.firstValue.bind(this);
30
+ this.queryBuilder.lastValue = this.lastValue.bind(this);
31
+ this.queryBuilder.nthValue = this.nthValue.bind(this);
32
+ this.queryBuilder.cumeDist = this.cumeDist.bind(this);
33
+ this.queryBuilder.percentRank = this.percentRank.bind(this);
34
+ }
35
+
36
+ /**
37
+ * 定义窗口框架
38
+ * @param {Object} frame - 窗口框架配置
39
+ * @returns {QueryBuilder} QueryBuilder 实例
40
+ */
41
+ windowFrame(frame) {
42
+ if (!this.queryBuilder.query.window) {
43
+ this.queryBuilder.query.window = {};
44
+ }
45
+ this.queryBuilder.query.window.frame = frame;
46
+ return this.queryBuilder;
47
+ }
48
+
49
+ /**
50
+ * NTILE 窗口函数
51
+ * @param {number} buckets - 桶数
52
+ * @param {string} alias - 列别名
53
+ * @param {string} windowName - 窗口名称
54
+ * @returns {QueryBuilder} QueryBuilder 实例
55
+ */
56
+ ntile(buckets, alias = "ntile", windowName = null) {
57
+ return this.over("NTILE", [buckets], windowName, alias);
58
+ }
59
+
60
+ /**
61
+ * 窗口分区
62
+ * @param {...string} columns - 分区列
63
+ * @returns {QueryBuilder} QueryBuilder 实例
64
+ */
65
+ partitionBy(...columns) {
66
+ if (!this.queryBuilder.query.window) {
67
+ this.queryBuilder.query.window = {};
68
+ }
69
+ this.queryBuilder.query.window.partitionBy = columns;
70
+ return this.queryBuilder;
71
+ }
72
+
73
+ /**
74
+ * 应用窗口函数
75
+ * @param {string} functionName - 窗口函数名
76
+ * @param {Array} args - 函数参数
77
+ * @param {string} windowName - 窗口名称
78
+ * @param {string} alias - 列别名
79
+ * @returns {QueryBuilder} QueryBuilder 实例
80
+ */
81
+ over(functionName, args = [], windowName = null, alias = null) {
82
+ const argsStr =
83
+ args.length > 0
84
+ ? args.map((arg) => this.queryBuilder.wrapColumn(arg)).join(", ")
85
+ : "*";
86
+
87
+ const windowClause = windowName ? `OVER (${windowName})` : "OVER ()";
88
+ const selectExpr = `${functionName}(${argsStr}) ${windowClause}`;
89
+
90
+ if (alias) {
91
+ this.queryBuilder.query.columns.push(`${selectExpr} as ${alias}`);
92
+ } else {
93
+ this.queryBuilder.query.columns.push(selectExpr);
94
+ }
95
+
96
+ return this.queryBuilder;
97
+ }
98
+
99
+ /**
100
+ * 行号窗口函数
101
+ * @param {string} alias - 列别名
102
+ * @param {string} windowName - 窗口名称
103
+ * @returns {QueryBuilder} QueryBuilder 实例
104
+ */
105
+ rowNumber(alias = "row_number", windowName = null) {
106
+ return this.over("ROW_NUMBER", [], windowName, alias);
107
+ }
108
+
109
+ /**
110
+ * 排名窗口函数
111
+ * @param {string} alias - 列别名
112
+ * @param {string} windowName - 窗口名称
113
+ * @returns {QueryBuilder} QueryBuilder 实例
114
+ */
115
+ rank(alias = "rank", windowName = null) {
116
+ return this.over("RANK", [], windowName, alias);
117
+ }
118
+
119
+ /**
120
+ * 密集排名窗口函数
121
+ * @param {string} alias - 列别名
122
+ * @param {string} windowName - 窗口名称
123
+ * @returns {QueryBuilder} QueryBuilder 实例
124
+ */
125
+ denseRank(alias = "dense_rank", windowName = null) {
126
+ return this.over("DENSE_RANK", [], windowName, alias);
127
+ }
128
+
129
+ /**
130
+ * LEAD 窗口函数
131
+ * @param {string} column - 列名
132
+ * @param {number} offset - 偏移量(默认:1)
133
+ * @param {*} defaultValue - 默认值
134
+ * @param {string} alias - 列别名
135
+ * @param {string} windowName - 窗口名称
136
+ * @returns {QueryBuilder} QueryBuilder 实例
137
+ */
138
+ lead(column, offset = 1, defaultValue = null, alias = null, windowName = null) {
139
+ const args = [this.queryBuilder.wrapColumn(column), offset];
140
+ if (defaultValue !== null) {
141
+ args.push(defaultValue);
142
+ }
143
+
144
+ const finalAlias = alias || `lead_${column}`;
145
+ return this.over("LEAD", args, windowName, finalAlias);
146
+ }
147
+
148
+ /**
149
+ * LAG 窗口函数
150
+ * @param {string} column - 列名
151
+ * @param {number} offset - 偏移量(默认:1)
152
+ * @param {*} defaultValue - 默认值
153
+ * @param {string} alias - 列别名
154
+ * @param {string} windowName - 窗口名称
155
+ * @returns {QueryBuilder} QueryBuilder 实例
156
+ */
157
+ lag(column, offset = 1, defaultValue = null, alias = null, windowName = null) {
158
+ const args = [this.queryBuilder.wrapColumn(column), offset];
159
+ if (defaultValue !== null) {
160
+ args.push(defaultValue);
161
+ }
162
+
163
+ const finalAlias = alias || `lag_${column}`;
164
+ return this.over("LAG", args, windowName, finalAlias);
165
+ }
166
+
167
+ /**
168
+ * FIRST_VALUE 窗口函数
169
+ * @param {string} column - 列名
170
+ * @param {string} alias - 列别名
171
+ * @param {string} windowName - 窗口名称
172
+ * @returns {QueryBuilder} QueryBuilder 实例
173
+ */
174
+ firstValue(column, alias = null, windowName = null) {
175
+ const finalAlias = alias || `first_value_${column}`;
176
+ return this.over(
177
+ "FIRST_VALUE",
178
+ [this.queryBuilder.wrapColumn(column)],
179
+ windowName,
180
+ finalAlias
181
+ );
182
+ }
183
+
184
+ /**
185
+ * LAST_VALUE 窗口函数
186
+ * @param {string} column - 列名
187
+ * @param {string} alias - 列别名
188
+ * @param {string} windowName - 窗口名称
189
+ * @returns {QueryBuilder} QueryBuilder 实例
190
+ */
191
+ lastValue(column, alias = null, windowName = null) {
192
+ const finalAlias = alias || `last_value_${column}`;
193
+ return this.over(
194
+ "LAST_VALUE",
195
+ [this.queryBuilder.wrapColumn(column)],
196
+ windowName,
197
+ finalAlias
198
+ );
199
+ }
200
+
201
+ /**
202
+ * NTH_VALUE 窗口函数
203
+ * @param {string} column - 列名
204
+ * @param {number} n - 第 N 个值
205
+ * @param {string} alias - 列别名
206
+ * @param {string} windowName - 窗口名称
207
+ * @returns {QueryBuilder} QueryBuilder 实例
208
+ */
209
+ nthValue(column, n, alias = null, windowName = null) {
210
+ const finalAlias = alias || `nth_value_${column}_${n}`;
211
+ return this.over(
212
+ "NTH_VALUE",
213
+ [this.queryBuilder.wrapColumn(column), n],
214
+ windowName,
215
+ finalAlias
216
+ );
217
+ }
218
+
219
+ /**
220
+ * 累积分布窗口函数
221
+ * @param {string} alias - 列别名
222
+ * @param {string} windowName - 窗口名称
223
+ * @returns {QueryBuilder} QueryBuilder 实例
224
+ */
225
+ cumeDist(alias = "cume_dist", windowName = null) {
226
+ return this.over("CUME_DIST", [], windowName, alias);
227
+ }
228
+
229
+ /**
230
+ * 百分比排名窗口函数
231
+ * @param {string} alias - 列别名
232
+ * @param {string} windowName - 窗口名称
233
+ * @returns {QueryBuilder} QueryBuilder 实例
234
+ */
235
+ percentRank(alias = "percent_rank", windowName = null) {
236
+ return this.over("PERCENT_RANK", [], windowName, alias);
237
+ }
238
+
239
+ /**
240
+ * 构建窗口函数 SQL
241
+ * @param {Object} windowConfig - 窗口配置
242
+ * @returns {string} SQL 片段
243
+ */
244
+ buildWindowSQL(windowConfig) {
245
+ if (!windowConfig) return "";
246
+
247
+ const parts = [];
248
+
249
+ if (windowConfig.partitionBy && windowConfig.partitionBy.length > 0) {
250
+ const partitionColumns = windowConfig.partitionBy
251
+ .map((col) => this.queryBuilder.wrapColumn(col))
252
+ .join(", ");
253
+ parts.push(`PARTITION BY ${partitionColumns}`);
254
+ }
255
+
256
+ if (windowConfig.orderBy && windowConfig.orderBy.length > 0) {
257
+ const orderColumns = windowConfig.orderBy
258
+ .map((order) => {
259
+ if (typeof order === "object" && order.raw) {
260
+ return order.raw;
261
+ }
262
+ return `${this.queryBuilder.wrapColumn(order.column)} ${order.direction}`;
263
+ })
264
+ .join(", ");
265
+ parts.push(`ORDER BY ${orderColumns}`);
266
+ }
267
+
268
+ if (windowConfig.frame) {
269
+ parts.push(this.buildWindowFrameSQL(windowConfig.frame));
270
+ }
271
+
272
+ return parts.length > 0 ? `(${parts.join(" ")})` : "()";
273
+ }
274
+
275
+ /**
276
+ * 构建窗口框架 SQL
277
+ * @param {Object} frame - 窗口框架配置
278
+ * @returns {string} SQL 片段
279
+ */
280
+ buildWindowFrameSQL(frame) {
281
+ if (!frame) return "";
282
+
283
+ const { type = "ROWS", start, end } = frame;
284
+ let frameStr = `${type}`;
285
+
286
+ if (start) {
287
+ frameStr += ` ${this.buildWindowFrameBound(start)}`;
288
+ if (end) {
289
+ frameStr += ` AND ${this.buildWindowFrameBound(end)}`;
290
+ }
291
+ }
292
+
293
+ return frameStr;
294
+ }
295
+
296
+ /**
297
+ * 构建窗口框架边界
298
+ * @param {Object|string} bound - 边界配置
299
+ * @returns {string} SQL 片段
300
+ */
301
+ buildWindowFrameBound(bound) {
302
+ if (typeof bound === "string") {
303
+ return bound;
304
+ }
305
+
306
+ if (bound.type === "PRECEDING") {
307
+ return `${bound.value} PRECEDING`;
308
+ } else if (bound.type === "FOLLOWING") {
309
+ return `${bound.value} FOLLOWING`;
310
+ } else if (bound.type === "CURRENT_ROW") {
311
+ return "CURRENT ROW";
312
+ } else if (bound.type === "UNBOUNDED") {
313
+ return "UNBOUNDED PRECEDING";
314
+ }
315
+
316
+ return "CURRENT ROW";
317
+ }
318
+
319
+ /**
320
+ * 获取支持的窗口函数列表
321
+ * @returns {Array} 支持的窗口函数
322
+ */
323
+ getSupportedFunctions() {
324
+ return [
325
+ "ROW_NUMBER",
326
+ "RANK",
327
+ "DENSE_RANK",
328
+ "NTILE",
329
+ "LEAD",
330
+ "LAG",
331
+ "FIRST_VALUE",
332
+ "LAST_VALUE",
333
+ "NTH_VALUE",
334
+ "CUME_DIST",
335
+ "PERCENT_RANK",
336
+ "AVG",
337
+ "SUM",
338
+ "COUNT",
339
+ "MIN",
340
+ "MAX",
341
+ ];
342
+ }
343
+ }