@yanit/jsondb 0.1.1

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 (118) hide show
  1. package/README.md +903 -0
  2. package/dist/bin/cli-export.d.ts +7 -0
  3. package/dist/bin/cli-export.d.ts.map +1 -0
  4. package/dist/bin/cli-export.js +318 -0
  5. package/dist/bin/cli-export.js.map +1 -0
  6. package/dist/bin/cli-import.d.ts +7 -0
  7. package/dist/bin/cli-import.d.ts.map +1 -0
  8. package/dist/bin/cli-import.js +298 -0
  9. package/dist/bin/cli-import.js.map +1 -0
  10. package/dist/bin/server.d.ts +7 -0
  11. package/dist/bin/server.d.ts.map +1 -0
  12. package/dist/bin/server.js +92 -0
  13. package/dist/bin/server.js.map +1 -0
  14. package/dist/examples/sql-example.d.ts +7 -0
  15. package/dist/examples/sql-example.d.ts.map +1 -0
  16. package/dist/examples/sql-example.js +131 -0
  17. package/dist/examples/sql-example.js.map +1 -0
  18. package/dist/src/BulkOp.d.ts +74 -0
  19. package/dist/src/BulkOp.d.ts.map +1 -0
  20. package/dist/src/BulkOp.js +143 -0
  21. package/dist/src/BulkOp.js.map +1 -0
  22. package/dist/src/Collection.d.ts +232 -0
  23. package/dist/src/Collection.d.ts.map +1 -0
  24. package/dist/src/Collection.js +705 -0
  25. package/dist/src/Collection.js.map +1 -0
  26. package/dist/src/Cursor.d.ts +94 -0
  27. package/dist/src/Cursor.d.ts.map +1 -0
  28. package/dist/src/Cursor.js +259 -0
  29. package/dist/src/Cursor.js.map +1 -0
  30. package/dist/src/Database.d.ts +98 -0
  31. package/dist/src/Database.d.ts.map +1 -0
  32. package/dist/src/Database.js +198 -0
  33. package/dist/src/Database.js.map +1 -0
  34. package/dist/src/Operators.d.ts +73 -0
  35. package/dist/src/Operators.d.ts.map +1 -0
  36. package/dist/src/Operators.js +339 -0
  37. package/dist/src/Operators.js.map +1 -0
  38. package/dist/src/QueryCache.d.ts +87 -0
  39. package/dist/src/QueryCache.d.ts.map +1 -0
  40. package/dist/src/QueryCache.js +155 -0
  41. package/dist/src/QueryCache.js.map +1 -0
  42. package/dist/src/SQLExecutor.d.ts +60 -0
  43. package/dist/src/SQLExecutor.d.ts.map +1 -0
  44. package/dist/src/SQLExecutor.js +317 -0
  45. package/dist/src/SQLExecutor.js.map +1 -0
  46. package/dist/src/SQLParser.d.ts +181 -0
  47. package/dist/src/SQLParser.d.ts.map +1 -0
  48. package/dist/src/SQLParser.js +640 -0
  49. package/dist/src/SQLParser.js.map +1 -0
  50. package/dist/src/Schema.d.ts +92 -0
  51. package/dist/src/Schema.d.ts.map +1 -0
  52. package/dist/src/Schema.js +253 -0
  53. package/dist/src/Schema.js.map +1 -0
  54. package/dist/src/Transaction.d.ts +118 -0
  55. package/dist/src/Transaction.d.ts.map +1 -0
  56. package/dist/src/Transaction.js +233 -0
  57. package/dist/src/Transaction.js.map +1 -0
  58. package/dist/src/Utils.d.ts +68 -0
  59. package/dist/src/Utils.d.ts.map +1 -0
  60. package/dist/src/Utils.js +187 -0
  61. package/dist/src/Utils.js.map +1 -0
  62. package/dist/src/errors.d.ts +58 -0
  63. package/dist/src/errors.d.ts.map +1 -0
  64. package/dist/src/errors.js +85 -0
  65. package/dist/src/errors.js.map +1 -0
  66. package/dist/src/index.d.ts +39 -0
  67. package/dist/src/index.d.ts.map +1 -0
  68. package/dist/src/index.js +44 -0
  69. package/dist/src/index.js.map +1 -0
  70. package/dist/test/basic.test.d.ts +5 -0
  71. package/dist/test/basic.test.d.ts.map +1 -0
  72. package/dist/test/basic.test.js +283 -0
  73. package/dist/test/basic.test.js.map +1 -0
  74. package/dist/test/index.test.d.ts +5 -0
  75. package/dist/test/index.test.d.ts.map +1 -0
  76. package/dist/test/index.test.js +126 -0
  77. package/dist/test/index.test.js.map +1 -0
  78. package/dist/test/jsonb.test.d.ts +5 -0
  79. package/dist/test/jsonb.test.d.ts.map +1 -0
  80. package/dist/test/jsonb.test.js +165 -0
  81. package/dist/test/jsonb.test.js.map +1 -0
  82. package/dist/test/optimization.test.d.ts +6 -0
  83. package/dist/test/optimization.test.d.ts.map +1 -0
  84. package/dist/test/optimization.test.js +196 -0
  85. package/dist/test/optimization.test.js.map +1 -0
  86. package/dist/test/schema.test.d.ts +5 -0
  87. package/dist/test/schema.test.d.ts.map +1 -0
  88. package/dist/test/schema.test.js +197 -0
  89. package/dist/test/schema.test.js.map +1 -0
  90. package/dist/test/sql.test.d.ts +7 -0
  91. package/dist/test/sql.test.d.ts.map +1 -0
  92. package/dist/test/sql.test.js +21 -0
  93. package/dist/test/sql.test.js.map +1 -0
  94. package/package.json +73 -0
  95. package/src/BulkOp.js +181 -0
  96. package/src/BulkOp.ts +191 -0
  97. package/src/Collection.js +843 -0
  98. package/src/Collection.ts +896 -0
  99. package/src/Cursor.js +315 -0
  100. package/src/Cursor.ts +319 -0
  101. package/src/Database.js +244 -0
  102. package/src/Database.ts +268 -0
  103. package/src/Operators.js +382 -0
  104. package/src/Operators.ts +375 -0
  105. package/src/QueryCache.js +190 -0
  106. package/src/QueryCache.ts +208 -0
  107. package/src/SQLExecutor.ts +391 -0
  108. package/src/SQLParser.ts +814 -0
  109. package/src/Schema.js +292 -0
  110. package/src/Schema.ts +317 -0
  111. package/src/Transaction.js +291 -0
  112. package/src/Transaction.ts +313 -0
  113. package/src/Utils.js +205 -0
  114. package/src/Utils.ts +205 -0
  115. package/src/errors.js +93 -0
  116. package/src/errors.ts +93 -0
  117. package/src/index.js +90 -0
  118. package/src/index.ts +106 -0
@@ -0,0 +1,208 @@
1
+ /**
2
+ * 查询结果缓存模块
3
+ * 缓存相同查询的结果,提升重复查询性能
4
+ */
5
+
6
+ import { createHash } from 'crypto';
7
+
8
+ /**
9
+ * 缓存条目接口
10
+ */
11
+ interface CacheEntry {
12
+ data: unknown;
13
+ createdAt: number;
14
+ expiresAt: number;
15
+ lastAccessed: number;
16
+ }
17
+
18
+ /**
19
+ * 查询缓存选项
20
+ */
21
+ interface QueryCacheOptions {
22
+ maxSize?: number;
23
+ ttl?: number;
24
+ }
25
+
26
+ /**
27
+ * 查询缓存类
28
+ */
29
+ export class QueryCache {
30
+ maxSize: number;
31
+ ttl: number;
32
+ cache: Map<string, CacheEntry>;
33
+ hits: number;
34
+ misses: number;
35
+
36
+ constructor(options: QueryCacheOptions = {}) {
37
+ this.maxSize = options.maxSize || 1000;
38
+ this.ttl = options.ttl || 60000;
39
+ this.cache = new Map();
40
+ this.hits = 0;
41
+ this.misses = 0;
42
+ }
43
+
44
+ /**
45
+ * 生成查询缓存键
46
+ */
47
+ generateKey(collection: string, query: Record<string, unknown>, options: Record<string, unknown> = {}): string {
48
+ const keyData = JSON.stringify({
49
+ collection,
50
+ query,
51
+ options: {
52
+ sort: options.sort,
53
+ limit: options.limit,
54
+ skip: options.skip,
55
+ projection: options.projection
56
+ }
57
+ });
58
+
59
+ return createHash('sha256').update(keyData).digest('hex');
60
+ }
61
+
62
+ /**
63
+ * 获取缓存
64
+ */
65
+ get(key: string): unknown | null {
66
+ const entry = this.cache.get(key);
67
+
68
+ if (!entry) {
69
+ this.misses++;
70
+ return null;
71
+ }
72
+
73
+ // 检查是否过期
74
+ if (Date.now() > entry.expiresAt) {
75
+ this.cache.delete(key);
76
+ this.misses++;
77
+ return null;
78
+ }
79
+
80
+ // 更新访问时间(LRU)
81
+ entry.lastAccessed = Date.now();
82
+ this.hits++;
83
+
84
+ return entry.data;
85
+ }
86
+
87
+ /**
88
+ * 设置缓存
89
+ */
90
+ set(key: string, data: unknown, ttl?: number): void {
91
+ // 如果缓存已满,删除最久未使用的条目
92
+ if (this.cache.size >= this.maxSize) {
93
+ this._evictOldest();
94
+ }
95
+
96
+ this.cache.set(key, {
97
+ data,
98
+ createdAt: Date.now(),
99
+ expiresAt: Date.now() + (ttl || this.ttl),
100
+ lastAccessed: Date.now()
101
+ });
102
+ }
103
+
104
+ /**
105
+ * 删除缓存
106
+ */
107
+ delete(key: string): void {
108
+ this.cache.delete(key);
109
+ }
110
+
111
+ /**
112
+ * 清空缓存
113
+ */
114
+ clear(): void {
115
+ this.cache.clear();
116
+ this.hits = 0;
117
+ this.misses = 0;
118
+ }
119
+
120
+ /**
121
+ * 删除与集合相关的所有缓存
122
+ */
123
+ invalidateCollection(collection: string): void {
124
+ for (const [key] of this.cache.entries()) {
125
+ if (key.includes(collection)) {
126
+ this.cache.delete(key);
127
+ }
128
+ }
129
+ }
130
+
131
+ /**
132
+ * 删除最久未使用的条目(LRU)
133
+ */
134
+ private _evictOldest(): void {
135
+ let oldestKey: string | null = null;
136
+ let oldestTime = Infinity;
137
+
138
+ for (const [key, entry] of this.cache.entries()) {
139
+ if (entry.lastAccessed < oldestTime) {
140
+ oldestTime = entry.lastAccessed;
141
+ oldestKey = key;
142
+ }
143
+ }
144
+
145
+ if (oldestKey) {
146
+ this.cache.delete(oldestKey);
147
+ }
148
+ }
149
+
150
+ /**
151
+ * 获取缓存统计
152
+ */
153
+ getStats(): {
154
+ size: number;
155
+ maxSize: number;
156
+ hits: number;
157
+ misses: number;
158
+ hitRate: string;
159
+ ttl: number;
160
+ } {
161
+ const total = this.hits + this.misses;
162
+ return {
163
+ size: this.cache.size,
164
+ maxSize: this.maxSize,
165
+ hits: this.hits,
166
+ misses: this.misses,
167
+ hitRate: total > 0 ? ((this.hits / total) * 100).toFixed(2) + '%' : '0%',
168
+ ttl: this.ttl
169
+ };
170
+ }
171
+ }
172
+
173
+ /**
174
+ * 全局查询缓存实例
175
+ */
176
+ export const globalQueryCache = new QueryCache({
177
+ maxSize: 500,
178
+ ttl: 30000 // 30 秒
179
+ });
180
+
181
+ /**
182
+ * 缓存查询装饰器
183
+ */
184
+ export function cacheQuery(
185
+ queryFn: (this: unknown, collection: { name: string }, query: Record<string, unknown>, queryOptions: Record<string, unknown>) => Promise<unknown>,
186
+ options: { cache?: QueryCache; ttl?: number } = {}
187
+ ) {
188
+ const cache = options.cache || globalQueryCache;
189
+ const ttl = options.ttl;
190
+
191
+ return async function(this: unknown, collection: { name: string }, query: Record<string, unknown>, queryOptions: Record<string, unknown>) {
192
+ const key = cache.generateKey(collection.name, query, queryOptions);
193
+
194
+ // 尝试从缓存获取
195
+ const cached = cache.get(key);
196
+ if (cached !== null) {
197
+ return cached;
198
+ }
199
+
200
+ // 执行查询
201
+ const result = await queryFn.call(this, collection, query, queryOptions);
202
+
203
+ // 存入缓存
204
+ cache.set(key, result, ttl);
205
+
206
+ return result;
207
+ };
208
+ }
@@ -0,0 +1,391 @@
1
+ /**
2
+ * SQL 执行器模块
3
+ * 将解析后的 SQL 语句转换为 JSONDB Collection API 调用
4
+ */
5
+
6
+ import type { Collection } from './Collection.js';
7
+ import type {
8
+ SQLStatement,
9
+ SelectStatement,
10
+ InsertStatement,
11
+ UpdateStatement,
12
+ DeleteStatement,
13
+ WhereClause
14
+ } from './SQLParser.js';
15
+ import { parseSQL } from './SQLParser.js';
16
+ import { matchQuery } from './Operators.js';
17
+
18
+ /**
19
+ * SQL 执行结果
20
+ */
21
+ export interface SQLExecutionResult {
22
+ success: boolean;
23
+ data?: unknown[];
24
+ affectedRows?: number;
25
+ insertId?: string;
26
+ error?: string;
27
+ }
28
+
29
+ /**
30
+ * SQL 执行器类
31
+ */
32
+ export class SQLExecutor {
33
+ private collection: Collection;
34
+
35
+ constructor(collection: Collection) {
36
+ this.collection = collection;
37
+ }
38
+
39
+ /**
40
+ * 执行 SQL 语句
41
+ */
42
+ async execute(statement: SQLStatement): Promise<SQLExecutionResult> {
43
+ try {
44
+ switch (statement.type) {
45
+ case 'SELECT':
46
+ return await this.executeSelect(statement);
47
+ case 'INSERT':
48
+ return await this.executeInsert(statement);
49
+ case 'UPDATE':
50
+ return await this.executeUpdate(statement);
51
+ case 'DELETE':
52
+ return await this.executeDelete(statement);
53
+ default:
54
+ return {
55
+ success: false,
56
+ error: `不支持的 SQL 语句类型:${(statement as SQLStatement).type}`
57
+ };
58
+ }
59
+ } catch (error) {
60
+ return {
61
+ success: false,
62
+ error: `SQL 执行错误:${(error as Error).message}`
63
+ };
64
+ }
65
+ }
66
+
67
+ /**
68
+ * 执行 SELECT 语句
69
+ */
70
+ private async executeSelect(statement: SelectStatement): Promise<SQLExecutionResult> {
71
+ // 构建查询
72
+ let cursor = this.collection.find({});
73
+
74
+ // 应用 WHERE 子句
75
+ if (statement.where) {
76
+ const query = this.whereToQuery(statement.where);
77
+ cursor = this.collection.find(query);
78
+ }
79
+
80
+ // 应用 ORDER BY
81
+ if (statement.orderBy && statement.orderBy.length > 0) {
82
+ const sortSpec: Record<string, number> = {};
83
+ for (const { column, direction } of statement.orderBy) {
84
+ sortSpec[column] = direction === 'DESC' ? -1 : 1;
85
+ }
86
+ cursor = cursor.sort(sortSpec);
87
+ }
88
+
89
+ // 应用 LIMIT
90
+ if (statement.limit !== undefined) {
91
+ cursor = cursor.limit(statement.limit);
92
+ }
93
+
94
+ // 应用 OFFSET
95
+ if (statement.offset !== undefined) {
96
+ cursor = cursor.skip(statement.offset);
97
+ }
98
+
99
+ // 执行查询
100
+ let results = await cursor.toArray();
101
+
102
+ // 应用投影(列选择)
103
+ if (statement.columns && statement.columns.length > 0 && !statement.columns.includes('*')) {
104
+ const projection: Record<string, number> = {};
105
+ for (const col of statement.columns) {
106
+ projection[col] = 1;
107
+ }
108
+ results = results.map(doc => {
109
+ const projected: Record<string, unknown> = {};
110
+ for (const col of statement.columns) {
111
+ if (doc[col] !== undefined) {
112
+ projected[col] = doc[col];
113
+ }
114
+ }
115
+ return projected;
116
+ });
117
+ }
118
+
119
+ // 应用 DISTINCT
120
+ if (statement.distinct) {
121
+ const seen = new Set<string>();
122
+ results = results.filter(doc => {
123
+ const key = JSON.stringify(doc);
124
+ if (seen.has(key)) {
125
+ return false;
126
+ }
127
+ seen.add(key);
128
+ return true;
129
+ });
130
+ }
131
+
132
+ // 应用 GROUP BY (简化版)
133
+ if (statement.groupBy && statement.groupBy.length > 0) {
134
+ results = this.applyGroupBy(results, statement.groupBy);
135
+ }
136
+
137
+ return {
138
+ success: true,
139
+ data: results
140
+ };
141
+ }
142
+
143
+ /**
144
+ * 执行 INSERT 语句
145
+ */
146
+ private async executeInsert(statement: InsertStatement): Promise<SQLExecutionResult> {
147
+ const docs: Record<string, unknown>[] = [];
148
+
149
+ for (const row of statement.values) {
150
+ const doc: Record<string, unknown> = {};
151
+ for (let i = 0; i < statement.columns.length; i++) {
152
+ doc[statement.columns[i]] = row[i];
153
+ }
154
+ docs.push(doc);
155
+ }
156
+
157
+ if (docs.length === 1) {
158
+ const inserted = await this.collection.insertOne(docs[0]);
159
+ return {
160
+ success: true,
161
+ data: [inserted],
162
+ affectedRows: 1,
163
+ insertId: inserted._id as string
164
+ };
165
+ } else {
166
+ const result = await this.collection.insertMany(docs);
167
+ return {
168
+ success: true,
169
+ data: docs,
170
+ affectedRows: result.insertedCount,
171
+ insertId: result.insertedIds[0]
172
+ };
173
+ }
174
+ }
175
+
176
+ /**
177
+ * 执行 UPDATE 语句
178
+ */
179
+ private async executeUpdate(statement: UpdateStatement): Promise<SQLExecutionResult> {
180
+ // 构建 $set 对象
181
+ const $set: Record<string, unknown> = {};
182
+ for (const { column, value } of statement.set) {
183
+ $set[column] = value;
184
+ }
185
+
186
+ // 构建查询
187
+ let query: Record<string, unknown> = {};
188
+ if (statement.where) {
189
+ query = this.whereToQuery(statement.where);
190
+ }
191
+
192
+ const result = await this.collection.updateMany(query, { $set });
193
+
194
+ return {
195
+ success: true,
196
+ affectedRows: result.modifiedCount
197
+ };
198
+ }
199
+
200
+ /**
201
+ * 执行 DELETE 语句
202
+ */
203
+ private async executeDelete(statement: DeleteStatement): Promise<SQLExecutionResult> {
204
+ // 构建查询
205
+ let query: Record<string, unknown> = {};
206
+ if (statement.where) {
207
+ query = this.whereToQuery(statement.where);
208
+ }
209
+
210
+ const result = await this.collection.deleteMany(query);
211
+
212
+ return {
213
+ success: true,
214
+ affectedRows: result.deletedCount
215
+ };
216
+ }
217
+
218
+ /**
219
+ * 将 WHERE 子句转换为 MongoDB 风格查询
220
+ */
221
+ private whereToQuery(where: WhereClause): Record<string, unknown> {
222
+ switch (where.type) {
223
+ case 'condition':
224
+ return this.conditionToQuery(where.column, where.operator, where.value);
225
+
226
+ case 'and':
227
+ if (where.conditions.length === 0) return {};
228
+ if (where.conditions.length === 1) {
229
+ return this.whereToQuery(where.conditions[0]);
230
+ }
231
+ return {
232
+ $and: where.conditions.map(c => this.whereToQuery(c))
233
+ };
234
+
235
+ case 'or':
236
+ if (where.conditions.length === 0) return {};
237
+ if (where.conditions.length === 1) {
238
+ return this.whereToQuery(where.conditions[0]);
239
+ }
240
+ return {
241
+ $or: where.conditions.map(c => this.whereToQuery(c))
242
+ };
243
+
244
+ case 'not':
245
+ const condition = this.whereToQuery(where.condition);
246
+ return { $nor: [condition] };
247
+
248
+ default:
249
+ return {};
250
+ }
251
+ }
252
+
253
+ /**
254
+ * 将单个条件转换为查询对象
255
+ */
256
+ private conditionToQuery(column: string, operator: string, value: unknown): Record<string, unknown> {
257
+ const query: Record<string, unknown> = {};
258
+
259
+ switch (operator.toUpperCase()) {
260
+ case '=':
261
+ query[column] = value;
262
+ break;
263
+
264
+ case '!=':
265
+ case '<>':
266
+ query[column] = { $ne: value };
267
+ break;
268
+
269
+ case '<':
270
+ query[column] = { $lt: value };
271
+ break;
272
+
273
+ case '<=':
274
+ query[column] = { $lte: value };
275
+ break;
276
+
277
+ case '>':
278
+ query[column] = { $gt: value };
279
+ break;
280
+
281
+ case '>=':
282
+ query[column] = { $gte: value };
283
+ break;
284
+
285
+ case 'LIKE':
286
+ // 转换 SQL LIKE 到正则表达式
287
+ if (typeof value === 'string') {
288
+ let regex = value
289
+ .replace(/[.+?^${}()|[\]\\]/g, '\\$&') // 转义特殊字符
290
+ .replace(/%/g, '.*') // % 匹配任意字符
291
+ .replace(/_/g, '.'); // _ 匹配单个字符
292
+ query[column] = { $regex: new RegExp(`^${regex}$`, 'i') };
293
+ }
294
+ break;
295
+
296
+ case 'IN':
297
+ if (Array.isArray(value)) {
298
+ query[column] = { $in: value };
299
+ }
300
+ break;
301
+
302
+ case 'NOT IN':
303
+ if (Array.isArray(value)) {
304
+ query[column] = { $nin: value };
305
+ }
306
+ break;
307
+
308
+ case 'IS':
309
+ if (value === null) {
310
+ query[column] = { $exists: false };
311
+ } else if (value === true) {
312
+ query[column] = { $exists: true };
313
+ }
314
+ break;
315
+
316
+ case 'IS NOT':
317
+ if (value === null) {
318
+ query[column] = { $exists: true };
319
+ }
320
+ break;
321
+
322
+ case 'BETWEEN':
323
+ // 假设 value 是 [min, max] 数组
324
+ if (Array.isArray(value) && value.length === 2) {
325
+ query[column] = {
326
+ $gte: value[0],
327
+ $lte: value[1]
328
+ };
329
+ }
330
+ break;
331
+
332
+ default:
333
+ query[column] = { [`$${operator.toLowerCase()}`]: value };
334
+ }
335
+
336
+ return query;
337
+ }
338
+
339
+ /**
340
+ * 应用 GROUP BY (简化实现)
341
+ */
342
+ private applyGroupBy(
343
+ docs: Array<Record<string, unknown>>,
344
+ groupBy: string[]
345
+ ): Array<Record<string, unknown>> {
346
+ const groups = new Map<string, Array<Record<string, unknown>>>();
347
+
348
+ for (const doc of docs) {
349
+ const key = groupBy.map(col => JSON.stringify(doc[col])).join('|');
350
+ if (!groups.has(key)) {
351
+ groups.set(key, []);
352
+ }
353
+ groups.get(key)!.push(doc);
354
+ }
355
+
356
+ return Array.from(groups.entries()).map(([key, groupDocs]) => {
357
+ const result: Record<string, unknown> = {};
358
+
359
+ // 添加分组字段
360
+ const keyParts = key.split('|');
361
+ groupBy.forEach((col, i) => {
362
+ result[col] = JSON.parse(keyParts[i]);
363
+ });
364
+
365
+ // 添加聚合字段(简化:只添加计数)
366
+ result._count = groupDocs.length;
367
+
368
+ return result;
369
+ });
370
+ }
371
+ }
372
+
373
+ /**
374
+ * 在 Collection 上执行 SQL
375
+ */
376
+ export async function executeSQL(
377
+ collection: Collection,
378
+ sql: string
379
+ ): Promise<SQLExecutionResult> {
380
+ const parseResult = parseSQL(sql);
381
+
382
+ if (!parseResult.success || !parseResult.statement) {
383
+ return {
384
+ success: false,
385
+ error: parseResult.error || 'SQL 解析失败'
386
+ };
387
+ }
388
+
389
+ const executor = new SQLExecutor(collection);
390
+ return await executor.execute(parseResult.statement);
391
+ }