baja-lite 1.8.7 → 1.8.9

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/boot-remote.d.ts +1 -1
  2. package/boot-remote.js +6 -1
  3. package/boot.d.ts +1 -1
  4. package/boot.js +6 -1
  5. package/cache.d.ts +91 -0
  6. package/cache.js +515 -0
  7. package/const/index.d.ts +2 -0
  8. package/const/index.js +2 -0
  9. package/const/symbols.d.ts +73 -0
  10. package/const/symbols.js +78 -0
  11. package/const/types.d.ts +504 -0
  12. package/const/types.js +127 -0
  13. package/db/dao/format-dialects.d.ts +6 -0
  14. package/db/dao/format-dialects.js +8 -0
  15. package/db/dao/mysql.d.ts +44 -0
  16. package/db/dao/mysql.js +303 -0
  17. package/db/dao/postgresql.d.ts +44 -0
  18. package/db/dao/postgresql.js +322 -0
  19. package/db/dao/sqlite-remote.d.ts +46 -0
  20. package/db/dao/sqlite-remote.js +226 -0
  21. package/db/dao/sqlite.d.ts +41 -0
  22. package/db/dao/sqlite.js +237 -0
  23. package/db/index.d.ts +8 -0
  24. package/db/index.js +8 -0
  25. package/db/service.d.ts +778 -0
  26. package/db/service.js +1651 -0
  27. package/db/sql-template.d.ts +46 -0
  28. package/db/sql-template.js +660 -0
  29. package/db/stream-query.d.ts +607 -0
  30. package/db/stream-query.js +1626 -0
  31. package/index.d.ts +4 -1
  32. package/index.js +4 -1
  33. package/logger.d.ts +46 -0
  34. package/logger.js +35 -0
  35. package/package.json +3 -6
  36. package/sqlite.d.ts +1 -1
  37. package/sqlite.js +2 -1
  38. package/{test-mysql.js → test/test-mysql.js} +3 -2
  39. package/{test-postgresql.js → test/test-postgresql.js} +3 -2
  40. package/{test-sqlite.js → test/test-sqlite.js} +3 -2
  41. package/sql.d.ts +0 -2207
  42. package/sql.js +0 -5471
  43. /package/{test-mysql.d.ts → test/test-mysql.d.ts} +0 -0
  44. /package/{test-postgresql.d.ts → test/test-postgresql.d.ts} +0 -0
  45. /package/{test-sqlite.d.ts → test/test-sqlite.d.ts} +0 -0
  46. /package/{test-xml.d.ts → test/test-xml.d.ts} +0 -0
  47. /package/{test-xml.js → test/test-xml.js} +0 -0
package/db/service.js ADDED
@@ -0,0 +1,1651 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var _a, _b, _c;
11
+ import { _columns, _columnsNoId, _def, _deleteState, _fields, _Hump, _ids, _index, _logicIds, _stateFileName, DBType, Field, LGet, } from 'baja-lite-field';
12
+ import * as ite from 'iterare';
13
+ import { formatDialect, mysql, postgresql, sqlite } from 'sql-formatter';
14
+ import tslib from 'tslib';
15
+ import { Throw } from '../error.js';
16
+ import { excuteSplit, ExcuteSplitMode } from '../fn.js';
17
+ import { calc, ten2Any } from '../math.js';
18
+ import { C2P, C2P2, P2C } from '../object.js';
19
+ import { snowflake } from '../snowflake.js';
20
+ import { emptyString } from '../string.js';
21
+ import { _ClassName, _className, _comment, _Context, _dao, _DataConvert, _daoDBName, _dbType, _GlobalSqlOption, _inTransaction, _LoggerService, _primaryDB, _resultMap_SQLID, _sqlCache, _SqlOption, _sqlite_version, _tableName, _transformer, _vueName, } from '../const/symbols.js';
22
+ import { DeleteMode, InsertMode, SelectMode, SelectResult, SyncMode, TemplateResult, _defOption, } from '../const/types.js';
23
+ import { Sqlite } from './dao/sqlite.js';
24
+ import { SqliteRemote } from './dao/sqlite-remote.js';
25
+ import { flatData } from './sql-template.js';
26
+ import { StreamQuery } from './stream-query.js';
27
+ const iterate = ite.iterate;
28
+ const formatDialects = {
29
+ [DBType.Mysql]: mysql,
30
+ [DBType.Sqlite]: sqlite,
31
+ [DBType.SqliteRemote]: sqlite,
32
+ [DBType.Postgresql]: postgresql,
33
+ };
34
+ function P(skipConn = false) {
35
+ return (_target, propertyKey, descriptor) => {
36
+ const fn = descriptor.value;
37
+ descriptor.value = function (...args) {
38
+ let needRealseConn = true;
39
+ const startTime = +new Date();
40
+ // option
41
+ const option = args[0] = Object.assign({}, globalThis[_GlobalSqlOption], this[_SqlOption], args[0]);
42
+ option.sync ?? (option.sync = SyncMode.Async);
43
+ option.tableName = option?.tableName ?? this[_tableName];
44
+ option.dbName = option?.dbName ?? this[_daoDBName] ?? _primaryDB;
45
+ option.dbType = this[_dbType] ?? globalThis[_GlobalSqlOption].dbType ?? DBType.Mysql;
46
+ option.dao = globalThis[_dao][option.dbType][option.dbName];
47
+ // 错误日志输出函数:原实现里 `let args = ''` 把外层 rest 参数 `args` 给遮蔽了,
48
+ // 导致 args.length 永远是 0,params 日志永远打不出来,生产排查时丢失关键上下文。
49
+ const dumpArgs = (callArgs) => {
50
+ if (callArgs.length > 0 && callArgs[0] && callArgs[0].params) {
51
+ try {
52
+ return JSON.stringify(callArgs[0].params);
53
+ }
54
+ catch {
55
+ return '<unserializable params>';
56
+ }
57
+ }
58
+ return '';
59
+ };
60
+ if (option.dbType === DBType.Sqlite) {
61
+ if (!option.dao) {
62
+ const db = new Sqlite(new globalThis[_GlobalSqlOption].BetterSqlite3(option.dbName, { fileMustExist: false }));
63
+ if (globalThis[_dao][option.dbType][_primaryDB] === undefined) {
64
+ globalThis[_dao][option.dbType][_primaryDB] = db;
65
+ }
66
+ globalThis[_dao][option.dbType][option.dbName] = db;
67
+ option.dao = db;
68
+ }
69
+ Throw.if(option.sync === SyncMode.Async, 'sqlite can not Async!');
70
+ // 连接共享
71
+ if (skipConn === false && !option.conn) {
72
+ option.conn = option.dao.createConnection(SyncMode.Sync);
73
+ }
74
+ else {
75
+ needRealseConn = false;
76
+ }
77
+ try {
78
+ const result = fn.call(this, ...args);
79
+ globalThis[_LoggerService].log(`${propertyKey}:${option.sqlId ?? option.tableName}:use ${+new Date() - startTime}ms`);
80
+ return result;
81
+ }
82
+ catch (error) {
83
+ console.error(`${option.sqlId ?? option.tableName} service ${propertyKey} have an error:${error}, it's argumens: ${dumpArgs(args)}`);
84
+ throw error;
85
+ }
86
+ finally {
87
+ if (needRealseConn && option && option.conn) {
88
+ try {
89
+ option.conn.release(SyncMode.Sync);
90
+ }
91
+ catch (error) {
92
+ }
93
+ }
94
+ }
95
+ }
96
+ else if (option.dbType === DBType.SqliteRemote) {
97
+ if (!option.dao) {
98
+ globalThis[_GlobalSqlOption].SqliteRemote.service.initDB(option.dbName);
99
+ const db = new SqliteRemote(globalThis[_GlobalSqlOption].SqliteRemote.service, option.dbName);
100
+ if (globalThis[_dao][option.dbType][_primaryDB] === undefined) {
101
+ globalThis[_dao][option.dbType][_primaryDB] = db;
102
+ }
103
+ globalThis[_dao][option.dbType][option.dbName] = db;
104
+ option.dao = db;
105
+ }
106
+ Throw.if(option.sync === SyncMode.Sync, 'SqliteRemote remote can not sync!');
107
+ return (async () => {
108
+ try {
109
+ // 连接共享
110
+ if (skipConn === false && !option.conn) {
111
+ (option).conn = await option.dao.createConnection(SyncMode.Async);
112
+ }
113
+ else {
114
+ needRealseConn = false;
115
+ }
116
+ const result = await fn.call(this, ...args);
117
+ globalThis[_LoggerService].log(`${propertyKey}:${option.sqlId ?? option.tableName}:use ${+new Date() - startTime}ms`);
118
+ return result;
119
+ }
120
+ catch (error) {
121
+ console.error(`${option.sqlId ?? option.tableName} service ${propertyKey} have an error:${error}, it's argumens: ${dumpArgs(args)}`);
122
+ throw error;
123
+ }
124
+ finally {
125
+ if (needRealseConn && option && option.conn) {
126
+ try {
127
+ await option.conn.release(SyncMode.Async);
128
+ }
129
+ catch (error) {
130
+ }
131
+ }
132
+ }
133
+ })();
134
+ }
135
+ else if (option.dbType === DBType.Mysql) {
136
+ Throw.if(!option.dao, `not found db:${String(option.dbName)}(${option.dbType})`);
137
+ return (async () => {
138
+ try {
139
+ // 连接共享
140
+ if (skipConn === false && !option.conn) {
141
+ (option).conn = await option.dao.createConnection(SyncMode.Async);
142
+ }
143
+ else {
144
+ needRealseConn = false;
145
+ }
146
+ const result = await fn.call(this, ...args);
147
+ globalThis[_LoggerService].log(`${propertyKey}:${option.sqlId ?? option.tableName}:use ${+new Date() - startTime}ms`);
148
+ return result;
149
+ }
150
+ catch (error) {
151
+ console.error(`${option.sqlId ?? option.tableName} service ${propertyKey} have an error:${error}, it's argumens: ${dumpArgs(args)}`);
152
+ throw error;
153
+ }
154
+ finally {
155
+ if (needRealseConn && option && option.conn) {
156
+ try {
157
+ await option.conn.release(SyncMode.Async);
158
+ }
159
+ catch (error) {
160
+ }
161
+ }
162
+ }
163
+ })();
164
+ }
165
+ else if (option.dbType === DBType.Postgresql) {
166
+ Throw.if(!option.dao, `not found db:${String(option.dbName)}(${option.dbType})`);
167
+ return (async () => {
168
+ try {
169
+ // 连接共享
170
+ if (skipConn === false && !option.conn) {
171
+ (option).conn = await option.dao.createConnection(SyncMode.Async);
172
+ }
173
+ else {
174
+ needRealseConn = false;
175
+ }
176
+ const result = await fn.call(this, ...args);
177
+ globalThis[_LoggerService].log(`${propertyKey}:${option.sqlId ?? option.tableName}:use ${+new Date() - startTime}ms`);
178
+ return result;
179
+ }
180
+ catch (error) {
181
+ console.error(`${option.sqlId ?? option.tableName} service ${propertyKey} have an error:${error}, it's argumens: ${dumpArgs(args)}`);
182
+ throw error;
183
+ }
184
+ finally {
185
+ if (needRealseConn && option && option.conn) {
186
+ try {
187
+ await option.conn.release(SyncMode.Async);
188
+ }
189
+ catch (error) {
190
+ }
191
+ }
192
+ }
193
+ })();
194
+ }
195
+ };
196
+ };
197
+ }
198
+ const FieldFilter = (K, V, def, uuidColumn, option) => {
199
+ let ret = 0;
200
+ // 如果是插入操作且字段是UUID,则不进行空值检查
201
+ // 只有在非插入或者非UUID时,进行空置检查
202
+ if (option?.insert && uuidColumn) {
203
+ ret = 1;
204
+ if (V === undefined || emptyString(`${V ?? ''}`)) {
205
+ V = null;
206
+ }
207
+ }
208
+ else {
209
+ if (V === null) {
210
+ if (option?.skipNull !== true) {
211
+ ret = 1;
212
+ V = option?.insert && def && def.hasOwnProperty(K) ? def[K] : null;
213
+ }
214
+ }
215
+ else if (V === undefined) {
216
+ if (option?.skipUndefined !== true) {
217
+ ret = 1;
218
+ V = option?.insert && def && def.hasOwnProperty(K) ? def[K] : null;
219
+ }
220
+ }
221
+ else if (emptyString(`${V ?? ''}`)) {
222
+ if (option?.skipEmptyString !== true) {
223
+ ret = 1;
224
+ V = option?.insert && def && def.hasOwnProperty(K) ? def[K] : '';
225
+ }
226
+ }
227
+ else {
228
+ ret = 1;
229
+ }
230
+ }
231
+ if (ret === 1) {
232
+ option?.finalColumns?.add(K);
233
+ option?.tempColumns?.push(K);
234
+ }
235
+ return [ret, V];
236
+ };
237
+ export const DB = (config) => {
238
+ return function (constructor) {
239
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
240
+ const __ids = Reflect.getMetadata(_ids, config.clz.prototype) || new Array;
241
+ const __logicIds = Reflect.getMetadata(_logicIds, config.clz.prototype) || new Array;
242
+ const __fields = Reflect.getMetadata(_fields, config.clz.prototype);
243
+ const __columns = Reflect.getMetadata(_columns, config.clz.prototype);
244
+ const __columnsNoId = Reflect.getMetadata(_columnsNoId, config.clz.prototype);
245
+ const __stateFileName = Reflect.getMetadata(_stateFileName, config.clz.prototype);
246
+ const __deleteState = Reflect.getMetadata(_deleteState, config.clz.prototype);
247
+ const __index = Reflect.getMetadata(_index, config.clz.prototype);
248
+ const __def = Reflect.getMetadata(_def, config.clz.prototype);
249
+ const __dbType = config.dbType;
250
+ const className = config.tableName?.replace(/_(\w)/g, (a, b) => b.toUpperCase());
251
+ const ClassName = className?.replace(/\w/, (v) => v.toUpperCase());
252
+ const vueName = config.tableName?.replace(/_/g, '-');
253
+ return _v = class extends constructor {
254
+ constructor() {
255
+ super(...arguments);
256
+ this[_a] = config.tableName;
257
+ this[_b] = className;
258
+ this[_c] = ClassName;
259
+ this[_d] = vueName;
260
+ this[_e] = config.dbName;
261
+ this[_f] = __dbType;
262
+ this[_g] = config.sqliteVersion;
263
+ this[_h] = Object.assign({}, _defOption, config);
264
+ this[_j] = __ids;
265
+ this[_k] = __logicIds;
266
+ this[_l] = __fields;
267
+ this[_m] = __columns;
268
+ this[_o] = __columnsNoId;
269
+ this[_p] = __index;
270
+ this[_q] = __def;
271
+ this[_r] = config.comment;
272
+ this[_s] = __stateFileName;
273
+ this[_t] = __deleteState;
274
+ this[_u] = (data, option) => {
275
+ return Object.fromEntries(iterate(option?.skipId ? __columnsNoId : __columns)
276
+ .map(K => [K, FieldFilter(K, data[K], __def, __fields[K].uuid || __fields[K].uuidShort, option)])
277
+ .filter(data => {
278
+ if (data[1][0] === 1) {
279
+ if (__fields[data[0]].Data2SQL) {
280
+ data[1][1] = __fields[data[0]].Data2SQL(data[1][1]);
281
+ }
282
+ if (option?.onFieldExists) {
283
+ option.onFieldExists(data[0], data[1][1]);
284
+ }
285
+ return true;
286
+ }
287
+ else {
288
+ return false;
289
+ }
290
+ })
291
+ .map(data => [data[0], data[1][1]])
292
+ .toArray());
293
+ };
294
+ }
295
+ },
296
+ _a = _tableName,
297
+ _b = _className,
298
+ _c = _ClassName,
299
+ _d = _vueName,
300
+ _e = _daoDBName,
301
+ _f = _dbType,
302
+ _g = _sqlite_version,
303
+ _h = _SqlOption,
304
+ _j = _ids,
305
+ _k = _logicIds,
306
+ _l = _fields,
307
+ _m = _columns,
308
+ _o = _columnsNoId,
309
+ _p = _index,
310
+ _q = _def,
311
+ _r = _comment,
312
+ _s = _stateFileName,
313
+ _t = _deleteState,
314
+ _u = _transformer,
315
+ _v;
316
+ };
317
+ };
318
+ /**
319
+ js项目中实体类注解替代品,只要确保函数被执行即可,举例:
320
+ ```
321
+ // 声明一个class
322
+ export class AmaFuck {}
323
+ DeclareClass(AmaFuck, [
324
+ { type: "String", name: "SellerSKU" },
325
+ { type: "String", name: "SellerSKU2" },
326
+ { type: "String", name: "site" }
327
+ ]);
328
+ ```
329
+ */
330
+ export function DeclareClass(clz, FieldOptions) {
331
+ for (const item of FieldOptions) {
332
+ tslib.__decorate([Field(item)], clz.prototype, item.P, void 0);
333
+ }
334
+ }
335
+ /**
336
+ JS项目中,service注解代替,举例:
337
+ ```
338
+ // 声明一个service,注意这里的let
339
+ export let AmaService = class AmaService extends SqlService {};
340
+ AmaService = DeclareService(AmaService, {
341
+ tableName: "ama_fuck2",
342
+ clz: AmaFuck,
343
+ dbType: DBType.Sqlite,
344
+ sqliteVersion: "0.0.3"
345
+ });
346
+ ```
347
+ */
348
+ export function DeclareService(clz, config) {
349
+ return tslib.__decorate([DB(config)], clz);
350
+ }
351
+ /**
352
+ ## 数据库服务
353
+ ### 注解DB
354
+
355
+ ### 泛型 T,同DB注解中的clz
356
+ ** 服务中所有方法默认以该类型为准
357
+ **
358
+
359
+ */
360
+ export class SqlService {
361
+ _insert(datas, option) {
362
+ const sqls = [];
363
+ const tableName = option.tableName;
364
+ switch (option?.mode) {
365
+ case InsertMode.InsertIfNotExists: {
366
+ const conditions = option.existConditionOtherThanIds || this[_ids];
367
+ Throw.if(!conditions, 'not found where condition for insertIfNotExists!');
368
+ Throw.if(conditions.length === 0, 'insertIfNotExists must have not null where!');
369
+ const where = iterate(conditions).map(c => `${this[_fields][c]?.C2()} = ?`).join(' AND ');
370
+ const finalColumns = new Set();
371
+ const whereColumns = conditions;
372
+ const params = [];
373
+ const questMarks = datas
374
+ .map(data => this[_transformer](data, { ...option, finalColumns, insert: true }))
375
+ .map(data => {
376
+ const questMark = new Array();
377
+ for (const column of finalColumns) {
378
+ const V = data.hasOwnProperty(column)
379
+ ? data[column]
380
+ : this[_def] && this[_def].hasOwnProperty(column)
381
+ ? this[_def][column]
382
+ : null;
383
+ if (V === null) {
384
+ const field = this[_fields][column];
385
+ if (field?.uuid) {
386
+ switch (option.dbType) {
387
+ case DBType.Postgresql:
388
+ questMark.push('gen_random_uuid()');
389
+ break;
390
+ default:
391
+ questMark.push('UUID()');
392
+ break;
393
+ }
394
+ }
395
+ else if (field?.uuidShort) {
396
+ switch (option.dbType) {
397
+ case DBType.Postgresql:
398
+ questMark.push(`encode(uuid_send(gen_random_uuid()::uuid),'base64')`);
399
+ break;
400
+ case DBType.Mysql:
401
+ questMark.push('UUID_SHORT()');
402
+ break;
403
+ default:
404
+ questMark.push('?');
405
+ params.push(V);
406
+ break;
407
+ }
408
+ }
409
+ else {
410
+ questMark.push('?');
411
+ params.push(V);
412
+ }
413
+ }
414
+ else {
415
+ questMark.push('?');
416
+ params.push(V);
417
+ }
418
+ }
419
+ for (const column of whereColumns) {
420
+ params.push(data.hasOwnProperty(column)
421
+ ? data[column]
422
+ : this[_def] && this[_def].hasOwnProperty(column)
423
+ ? this[_def][column]
424
+ : null);
425
+ }
426
+ return `SELECT ${questMark.join(',')} FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM ${tableName} WHERE ${where})`;
427
+ });
428
+ const columnNames = iterate(finalColumns).map(i => this[_fields][i]?.C2()).join(',');
429
+ const sql = formatDialect(`INSERT INTO
430
+ ${tableName}
431
+ (${columnNames})
432
+ ${questMarks.join(' UNION ALL ')};`, { dialect: formatDialects[option.dbType] });
433
+ sqls.push({ sql, params });
434
+ break;
435
+ }
436
+ case InsertMode.Replace: {
437
+ const finalColumns = new Set();
438
+ const params = [];
439
+ const questMarks = datas
440
+ .map(data => this[_transformer](data, { ...option, finalColumns, insert: true }))
441
+ .map(data => {
442
+ const questMark = new Array();
443
+ for (const column of finalColumns) {
444
+ const V = data.hasOwnProperty(column)
445
+ ? data[column]
446
+ : this[_def] && this[_def].hasOwnProperty(column)
447
+ ? this[_def][column]
448
+ : null;
449
+ if (V === null) {
450
+ const field = this[_fields][column];
451
+ if (field?.uuid) {
452
+ switch (option.dbType) {
453
+ case DBType.Postgresql:
454
+ questMark.push('gen_random_uuid()');
455
+ break;
456
+ default:
457
+ questMark.push('UUID()');
458
+ break;
459
+ }
460
+ }
461
+ else if (field?.uuidShort) {
462
+ switch (option.dbType) {
463
+ case DBType.Postgresql:
464
+ questMark.push(`encode(uuid_send(gen_random_uuid()::uuid),'base64')`);
465
+ break;
466
+ case DBType.Mysql:
467
+ questMark.push('UUID_SHORT()');
468
+ break;
469
+ default:
470
+ questMark.push('?');
471
+ params.push(V);
472
+ break;
473
+ }
474
+ }
475
+ else {
476
+ questMark.push('?');
477
+ params.push(V);
478
+ }
479
+ }
480
+ else {
481
+ questMark.push('?');
482
+ params.push(V);
483
+ }
484
+ }
485
+ return `(${questMark.join(',')})`;
486
+ });
487
+ const columnNames = iterate(finalColumns).map(i => this[_fields][i]?.C2()).join(',');
488
+ const sql = formatDialect(`
489
+ ${option.dbType === DBType.Mysql ? '' : 'INSERT OR'} REPLACE INTO
490
+ ${tableName}
491
+ (${columnNames})
492
+ VALUES ${questMarks};
493
+ `, { dialect: formatDialects[option.dbType] });
494
+ sqls.push({ sql, params });
495
+ break;
496
+ }
497
+ case InsertMode.Insert: {
498
+ const finalColumns = new Set();
499
+ const params = [];
500
+ const questMarks = datas
501
+ .map(data => this[_transformer](data, { ...option, finalColumns, insert: true }))
502
+ .map(data => {
503
+ const questMark = new Array();
504
+ for (const column of finalColumns) {
505
+ const V = data.hasOwnProperty(column)
506
+ ? data[column]
507
+ : this[_def] && this[_def].hasOwnProperty(column)
508
+ ? this[_def][column]
509
+ : null;
510
+ if (V === null) {
511
+ const field = this[_fields][column];
512
+ if (field?.uuid) {
513
+ switch (option.dbType) {
514
+ case DBType.Postgresql:
515
+ questMark.push('gen_random_uuid()');
516
+ break;
517
+ default:
518
+ questMark.push('UUID()');
519
+ break;
520
+ }
521
+ }
522
+ else if (field?.uuidShort) {
523
+ switch (option.dbType) {
524
+ case DBType.Postgresql:
525
+ questMark.push(`encode(uuid_send(gen_random_uuid()::uuid),'base64')`);
526
+ break;
527
+ case DBType.Mysql:
528
+ questMark.push('UUID_SHORT()');
529
+ break;
530
+ default:
531
+ questMark.push('?');
532
+ params.push(V);
533
+ break;
534
+ }
535
+ }
536
+ else {
537
+ questMark.push('?');
538
+ params.push(V);
539
+ }
540
+ }
541
+ else {
542
+ questMark.push('?');
543
+ params.push(V);
544
+ }
545
+ }
546
+ return `(${questMark.join(',')})`;
547
+ });
548
+ const columnNames = iterate(finalColumns).map(i => this[_fields][i]?.C2()).join(',');
549
+ const sql = formatDialect(`
550
+ INSERT INTO
551
+ ${tableName}
552
+ (${columnNames})
553
+ VALUES ${questMarks};
554
+ `, { dialect: formatDialects[option.dbType] });
555
+ sqls.push({ sql, params });
556
+ break;
557
+ }
558
+ case InsertMode.InsertWithTempTable: {
559
+ // 用 snowflake 替代 Math.random()——Math.random() 在高并发下可能碰撞,
560
+ // 同一连接里多次 InsertWithTempTable 会因为撞名 DDL 报错。
561
+ const tableTemp = `${option?.tableName}_${snowflake.generate()}`;
562
+ const tableTempESC = tableTemp;
563
+ sqls.push({ sql: `DROP TABLE IF EXISTS ${tableTempESC};` });
564
+ const finalColumns = new Set();
565
+ const params = [];
566
+ const questMarks = datas
567
+ .map(data => this[_transformer](data, { ...option, finalColumns, insert: true }))
568
+ .map(data => {
569
+ const questMark = new Array();
570
+ for (const column of finalColumns) {
571
+ const V = data.hasOwnProperty(column)
572
+ ? data[column]
573
+ : this[_def] && this[_def].hasOwnProperty(column)
574
+ ? this[_def][column]
575
+ : null;
576
+ if (V === null) {
577
+ const field = this[_fields][column];
578
+ if (field?.uuid) {
579
+ switch (option.dbType) {
580
+ case DBType.Postgresql:
581
+ questMark.push('gen_random_uuid()');
582
+ break;
583
+ default:
584
+ questMark.push('UUID()');
585
+ break;
586
+ }
587
+ }
588
+ else if (field?.uuidShort) {
589
+ switch (option.dbType) {
590
+ case DBType.Postgresql:
591
+ questMark.push(`encode(uuid_send(gen_random_uuid()::uuid),'base64')`);
592
+ break;
593
+ case DBType.Mysql:
594
+ questMark.push('UUID_SHORT()');
595
+ break;
596
+ default:
597
+ questMark.push('?');
598
+ params.push(V);
599
+ break;
600
+ }
601
+ }
602
+ else {
603
+ questMark.push('?');
604
+ params.push(V);
605
+ }
606
+ }
607
+ else {
608
+ questMark.push('?');
609
+ params.push(V);
610
+ }
611
+ }
612
+ return `(${questMark.join(',')})`;
613
+ });
614
+ const _sqls = this._createTable({ tableName: tableTemp, temp: true, columns: Array.from(finalColumns) });
615
+ sqls.push(..._sqls);
616
+ const columnNames = iterate(finalColumns).map(i => this[_fields][i]?.C2()).join(',');
617
+ sqls.push({
618
+ sql: formatDialect(`
619
+ INSERT INTO
620
+ ${tableTemp}
621
+ (${columnNames})
622
+ VALUES ${questMarks};
623
+ `, { dialect: formatDialects[option.dbType] }), params
624
+ });
625
+ sqls.push({
626
+ sql: formatDialect(`INSERT INTO ${option.tableName} (${columnNames})
627
+ SELECT ${columnNames} FROM ${tableTemp};`, { dialect: formatDialects[option.dbType] })
628
+ });
629
+ sqls.push({ sql: `DROP TABLE IF EXISTS ${tableTempESC};` });
630
+ break;
631
+ }
632
+ }
633
+ return sqls;
634
+ }
635
+ insert(option) {
636
+ option.mode ?? (option.mode = InsertMode.Insert);
637
+ const isArray = option.data instanceof Array;
638
+ const datas = option.data instanceof Array ? option.data : [option.data];
639
+ if (datas.length === 0)
640
+ return 0n;
641
+ if (option.sync === SyncMode.Sync) {
642
+ const fn = () => {
643
+ const result = excuteSplit(ExcuteSplitMode.SyncTrust, datas, _data => {
644
+ const sqls = this._insert(_data, option);
645
+ let result = 0n;
646
+ for (const { sql, params } of sqls) {
647
+ const dd = option.conn.execute(SyncMode.Sync, sql, params);
648
+ if (dd.insertId) {
649
+ result += BigInt(dd.insertId);
650
+ }
651
+ }
652
+ return result;
653
+ }, { everyLength: option?.every ? 1 : option?.maxDeal });
654
+ if (isArray)
655
+ return result;
656
+ else
657
+ return result[0];
658
+ };
659
+ if (option.dbType === DBType.SqliteRemote || option?.conn?.[_inTransaction]) {
660
+ return fn();
661
+ }
662
+ else {
663
+ return option?.dao?.transaction(SyncMode.Sync, fn, option?.conn);
664
+ }
665
+ }
666
+ else if (isArray) {
667
+ const fn = async () => {
668
+ const result = await excuteSplit(ExcuteSplitMode.AsyncTrust, datas, async (_data) => {
669
+ const sqls = this._insert(_data, option);
670
+ let result = 0n;
671
+ for (const { sql, params } of sqls) {
672
+ const dd = await option.conn.execute(SyncMode.Async, sql, params);
673
+ if (dd.insertId) {
674
+ result += BigInt(dd.insertId);
675
+ }
676
+ }
677
+ return result;
678
+ }, { everyLength: option?.every ? 1 : option?.maxDeal });
679
+ return result;
680
+ };
681
+ if (option.dbType === DBType.SqliteRemote || option?.conn?.[_inTransaction]) {
682
+ return fn();
683
+ }
684
+ else {
685
+ return option?.dao?.transaction(SyncMode.Async, fn, option?.conn);
686
+ }
687
+ }
688
+ else {
689
+ const fn = async () => {
690
+ const result = await excuteSplit(ExcuteSplitMode.AsyncTrust, datas, async (_data) => {
691
+ const sqls = this._insert(_data, option);
692
+ let result = 0n;
693
+ for (const { sql, params } of sqls) {
694
+ const dd = await option.conn.execute(SyncMode.Async, sql, params);
695
+ if (dd.insertId) {
696
+ result += BigInt(dd.insertId);
697
+ }
698
+ }
699
+ return result;
700
+ }, { everyLength: 1 });
701
+ return result[0];
702
+ };
703
+ if (option.dbType === DBType.SqliteRemote || option?.conn?.[_inTransaction]) {
704
+ return fn();
705
+ }
706
+ else {
707
+ return option?.dao?.transaction(SyncMode.Async, fn, option?.conn);
708
+ }
709
+ }
710
+ }
711
+ _update(datas, option) {
712
+ const sqls = [];
713
+ const tableName = option?.tableName;
714
+ const where = `WHEN ${iterate(this[_ids]).map(c => `${this[_fields][c]?.C2()} = ?`).join(' AND ')} THEN ?`;
715
+ const columnMaps = Object.fromEntries(this[_columnsNoId].map(c => [c, {
716
+ where: new Array(),
717
+ params: []
718
+ }]));
719
+ const params = [];
720
+ for (const data of datas) {
721
+ const ids = this[_ids].map(i => {
722
+ Throw.if(!data[i], `UPDATE ID NOT EXISTS!${JSON.stringify(data)}`);
723
+ return data[i];
724
+ });
725
+ this[_transformer](data, {
726
+ ...option,
727
+ skipId: true,
728
+ onFieldExists: (K, V) => {
729
+ columnMaps[K]?.where.push(where);
730
+ columnMaps[K]?.params.push(...ids, V);
731
+ }
732
+ });
733
+ }
734
+ const sql = formatDialect(`UPDATE ${tableName} SET ${iterate(this[_columnsNoId])
735
+ .filter(K => columnMaps[K].where.length > 0)
736
+ .map(K => {
737
+ params.push(...columnMaps[K].params);
738
+ return `${this[_fields][K]?.C2()} = CASE ${columnMaps[K].where.join(' ')} ELSE ${this[_fields][K]?.C2()} END`;
739
+ })
740
+ .join(',')};`, { dialect: formatDialects[option.dbType] });
741
+ sqls.push({ sql, params });
742
+ return sqls;
743
+ }
744
+ update(option) {
745
+ Throw.if(!this[_ids] || this[_ids].length === 0, 'not found id');
746
+ const datas = option.data instanceof Array ? option.data : [option.data];
747
+ if (datas.length === 0)
748
+ return 0;
749
+ if (option.sync === SyncMode.Sync) {
750
+ const fn = () => {
751
+ const result = excuteSplit(ExcuteSplitMode.SyncTrust, datas, _data => {
752
+ const sqls = this._update(_data, option);
753
+ let result = 0;
754
+ for (const { sql, params } of sqls) {
755
+ const dd = option.conn.execute(SyncMode.Sync, sql, params);
756
+ if (dd.affectedRows) {
757
+ result += dd.affectedRows;
758
+ }
759
+ }
760
+ return result;
761
+ }, { everyLength: option?.maxDeal });
762
+ return result.length > 0 ? result.reduce((a, b) => a + b) : 0;
763
+ };
764
+ if (option.dbType === DBType.SqliteRemote || option?.conn?.[_inTransaction]) {
765
+ return fn();
766
+ }
767
+ else {
768
+ return option?.dao?.transaction(SyncMode.Sync, fn, option?.conn);
769
+ }
770
+ }
771
+ else {
772
+ const fn = async () => {
773
+ const result = await excuteSplit(ExcuteSplitMode.AsyncTrust, datas, async (_data) => {
774
+ const sqls = this._update(_data, option);
775
+ let result = 0;
776
+ for (const { sql, params } of sqls) {
777
+ const dd = await option.conn.execute(SyncMode.Async, sql, params);
778
+ if (dd.affectedRows) {
779
+ result += dd.affectedRows;
780
+ }
781
+ }
782
+ return result;
783
+ }, { everyLength: option?.maxDeal });
784
+ return result.length > 0 ? result.reduce((a, b) => a + b) : 0;
785
+ };
786
+ if (option.dbType === DBType.SqliteRemote || option?.conn?.[_inTransaction]) {
787
+ return fn();
788
+ }
789
+ else {
790
+ return option?.dao?.transaction(SyncMode.Async, fn, option?.conn);
791
+ }
792
+ }
793
+ }
794
+ delete(option) {
795
+ Throw.if(!!this[_ids] && this[_ids].length > 1 && !option.where && !option.whereSql, 'muit id must set where!');
796
+ Throw.if((!this[_ids] || this[_ids].length === 0) && !option.where && !option.whereSql, 'if not set id on class, must set where!');
797
+ Throw.if(!option.id && !option.where && !option.whereSql, 'not found id or where!');
798
+ Throw.if(!!option.id && !!this[_ids] && this[_ids].length > 1, 'muit id must set where!');
799
+ Throw.if(!!option.id && !!option.where && !option.whereSql, 'id and where only one can set!');
800
+ option.mode ?? (option.mode = DeleteMode.Common);
801
+ const tableTemp = `${option?.tableName}_${snowflake.generate()}`;
802
+ const tableTempESC = tableTemp;
803
+ const tableNameESC = option?.tableName;
804
+ if (option.id) {
805
+ const idName = this[_ids][0];
806
+ const ids = option.id instanceof Array ? option.id : [option.id];
807
+ option.where = ids.map(i => ({ [idName]: i }));
808
+ }
809
+ const wheres = option.where instanceof Array ? option.where : [option.where];
810
+ if (wheres.length === 0 && (!option.whereSql || !option.whereParams)) {
811
+ return 0;
812
+ }
813
+ if (option.whereSql && option.whereParams) {
814
+ option.mode = DeleteMode.Common;
815
+ }
816
+ const sqls = [];
817
+ if (option.mode === DeleteMode.Common) {
818
+ let params;
819
+ let whereSql;
820
+ if (option.whereSql && option.whereParams) {
821
+ const gen = this._generSql(option.dbType, option.whereSql, option.whereParams);
822
+ whereSql = gen.sql;
823
+ params = gen.params;
824
+ }
825
+ else {
826
+ params = new Array();
827
+ whereSql = iterate(wheres).map(where => {
828
+ return `(
829
+ ${Object.entries(where).map(([K, V]) => {
830
+ params.push(V);
831
+ return `${this[_fields][K]?.C2()} = ?`;
832
+ }).join(' AND ')}
833
+ )`;
834
+ }).join(' OR ');
835
+ }
836
+ if (this[_stateFileName] !== undefined && option.forceDelete !== true) {
837
+ params.unshift(this[_deleteState]);
838
+ sqls.push({
839
+ sql: formatDialect(`
840
+ UPDATE ${tableNameESC} SET ${this[_fields][this[_stateFileName]]?.C2()} = ?
841
+ WHERE ${whereSql};
842
+ `, { dialect: formatDialects[option.dbType] }), params
843
+ });
844
+ }
845
+ else {
846
+ sqls.push({ sql: formatDialect(`DELETE FROM ${tableNameESC} WHERE ${whereSql};`, { dialect: formatDialects[option.dbType] }), params });
847
+ }
848
+ }
849
+ else {
850
+ sqls.push({ sql: `DROP TABLE IF EXISTS ${tableTempESC};` });
851
+ const delWhere = Object.keys(wheres[0]);
852
+ const _sqls = this._createTable({ tableName: tableTemp, temp: true, columns: delWhere, data: wheres, index: 'all', id: 'none' });
853
+ sqls.push(..._sqls);
854
+ switch (option.dbType) {
855
+ case DBType.Mysql: {
856
+ if (this[_stateFileName] !== undefined && option.forceDelete !== true) {
857
+ sqls.push({
858
+ sql: formatDialect(`UPDATE ${tableNameESC} a INNER JOIN ${tableTempESC} b ON ${delWhere.map(K => `a.${this[_fields][K]?.C2()} = b.${this[_fields][K]?.C2()}`).join(' AND ')}
859
+ SET a.${this[_fields][this[_stateFileName]]?.C2()} = ?;`, { dialect: formatDialects[option.dbType] }),
860
+ params: [this[_deleteState]]
861
+ });
862
+ }
863
+ else {
864
+ sqls.push({
865
+ sql: formatDialect(`DELETE a.* FROM ${tableNameESC} a INNER JOIN ${tableTempESC} b ON ${delWhere.map(K => `a.${this[_fields][K]?.C2()} = b.${this[_fields][K]?.C2()}`).join(' AND ')};`, { dialect: formatDialects[option.dbType] })
866
+ });
867
+ }
868
+ break;
869
+ }
870
+ case DBType.Sqlite:
871
+ case DBType.SqliteRemote: {
872
+ const columnNames = iterate(delWhere).map(K => this[_fields][K]?.C2()).join(',');
873
+ if (this[_stateFileName] !== undefined && option.forceDelete !== true) {
874
+ sqls.push({
875
+ sql: formatDialect(`UPDATE ${tableNameESC} SET ${this[_fields][this[_stateFileName]]?.C2()} = ?
876
+ WHERE (${columnNames}) IN (SELECT ${columnNames} FROM ${tableTempESC});`, { dialect: formatDialects[option.dbType] }),
877
+ params: [this[_deleteState]]
878
+ });
879
+ }
880
+ else {
881
+ sqls.push({ sql: formatDialect(`DELETE FROM ${tableNameESC} WHERE (${columnNames}) IN (SELECT ${columnNames} FROM ${tableTempESC});`, { dialect: formatDialects[option.dbType] }) });
882
+ }
883
+ break;
884
+ }
885
+ }
886
+ sqls.push({ sql: `DROP TABLE IF EXISTS ${tableTempESC};` });
887
+ }
888
+ if (option.sync === SyncMode.Sync) {
889
+ const fn = () => {
890
+ let result = 0;
891
+ for (const { sql, params } of sqls) {
892
+ const dd = option.conn.execute(SyncMode.Sync, sql, params);
893
+ result += dd.affectedRows;
894
+ }
895
+ return result;
896
+ };
897
+ if (option.dbType === DBType.SqliteRemote || option?.conn?.[_inTransaction]) {
898
+ return fn();
899
+ }
900
+ else {
901
+ return option?.dao?.transaction(SyncMode.Sync, fn, option?.conn);
902
+ }
903
+ }
904
+ else {
905
+ const fn = async () => {
906
+ let result = 0;
907
+ for (const { sql, params } of sqls) {
908
+ const dd = await option.conn.execute(SyncMode.Async, sql, params);
909
+ result += dd.affectedRows;
910
+ }
911
+ return result;
912
+ };
913
+ if (option.dbType === DBType.SqliteRemote || option?.conn?.[_inTransaction]) {
914
+ return fn();
915
+ }
916
+ else {
917
+ return option?.dao?.transaction(SyncMode.Async, fn, option?.conn);
918
+ }
919
+ }
920
+ }
921
+ _template(templateResult, result, error) {
922
+ switch (templateResult) {
923
+ case TemplateResult.AssertOne: {
924
+ Throw.if(!result || result.length !== 1, error);
925
+ return result[0];
926
+ }
927
+ case TemplateResult.NotSureOne: {
928
+ return result && result.length > 0 ? result[0] ?? null : null;
929
+ }
930
+ case TemplateResult.Many: {
931
+ return result;
932
+ }
933
+ case TemplateResult.Count: {
934
+ return result[0].ct;
935
+ }
936
+ }
937
+ }
938
+ template(option) {
939
+ Throw.if(!!this[_ids] && this[_ids].length > 1 && !option.where, `muit id must set where!(${option.tableName})`);
940
+ Throw.if((!this[_ids] || this[_ids].length === 0) && !option.where, `if not set id on class, must set where!(${option.tableName})`);
941
+ Throw.if(!option.id && !option.where, `not found id or where!(${option.tableName})`);
942
+ Throw.if(!!option.id && !!this[_ids] && this[_ids].length > 1, `muit id must set where!(${option.tableName})`);
943
+ Throw.if(!!option.id && !!option.where, `id and where only one can set!(${option.tableName})`);
944
+ option.mode ?? (option.mode = SelectMode.Common);
945
+ option.templateResult ?? (option.templateResult = TemplateResult.AssertOne);
946
+ option.error ?? (option.error = 'error data!');
947
+ const tableTemp = `${option?.tableName}_${snowflake.generate()}`;
948
+ const tableTempESC = tableTemp;
949
+ const tableNameESC = option?.tableName;
950
+ if (option.id) {
951
+ const idName = this[_ids][0];
952
+ const ids = option.id instanceof Array ? option.id : [option.id];
953
+ option.where = ids.map(i => ({ [idName]: i }));
954
+ }
955
+ const columns = option.templateResult === TemplateResult.Count ? 'COUNT(1) ct' : iterate((option.columns ?? this[_columns])).map((K) => `a.${this[_fields][K]?.C3()}`).join(',');
956
+ const wheres = option.where instanceof Array ? option.where : [option.where];
957
+ const sqls = [];
958
+ let resultIndex = -1;
959
+ if (option.mode === SelectMode.Common) {
960
+ const params = new Array();
961
+ const whereSql = formatDialect(iterate(wheres).map(where => this[_transformer](where, option)).map(where => {
962
+ return `SELECT ${columns} FROM ${tableNameESC} a WHERE
963
+ ${Object.entries(where).map(([K, V]) => {
964
+ params.push(V);
965
+ return `${this[_fields][K]?.C2()} = ?`;
966
+ }).join(' AND ')}`;
967
+ }).join(' UNION ALL '), { dialect: formatDialects[option.dbType] });
968
+ sqls.push({ sql: whereSql, params });
969
+ resultIndex = 0;
970
+ }
971
+ else {
972
+ sqls.push({ sql: `DROP TABLE IF EXISTS ${tableTempESC};` });
973
+ const delWhere = Object.keys(wheres[0]);
974
+ const _sqls = this._createTable({ tableName: tableTemp, temp: true, columns: delWhere, data: wheres, index: 'all', id: 'none' });
975
+ sqls.push(..._sqls);
976
+ resultIndex = sqls.length;
977
+ sqls.push({ sql: formatDialect(`SELECT ${columns} FROM ${tableNameESC} a INNER JOIN ${tableTempESC} b ON ${delWhere.map(K => `a.${this[_fields][K]?.C2()} = b.${this[_fields][K]?.C2()}`).join(' AND ')};`, { dialect: formatDialects[option.dbType] }) });
978
+ sqls.push({ sql: `DROP TABLE IF EXISTS ${tableTempESC};` });
979
+ }
980
+ if (option.sync === SyncMode.Sync) {
981
+ let result;
982
+ for (let i = 0; i < sqls.length; i++) {
983
+ if (i === resultIndex) {
984
+ result = option.conn.query(SyncMode.Sync, sqls[i]?.sql, sqls[i]?.params);
985
+ }
986
+ else {
987
+ option.conn.execute(SyncMode.Sync, sqls[i]?.sql, sqls[i]?.params);
988
+ }
989
+ }
990
+ return this._template(option.templateResult, result, option.error);
991
+ }
992
+ else {
993
+ return (async () => {
994
+ let result;
995
+ for (let i = 0; i < sqls.length; i++) {
996
+ if (i === resultIndex) {
997
+ result = await option.conn.query(SyncMode.Async, sqls[i]?.sql, sqls[i]?.params);
998
+ }
999
+ else {
1000
+ await option.conn.execute(SyncMode.Async, sqls[i]?.sql, sqls[i]?.params);
1001
+ }
1002
+ }
1003
+ return this._template(option.templateResult, result, option.error);
1004
+ })();
1005
+ }
1006
+ }
1007
+ _select(templateResult, result, def, errorMsg, hump, mapper, mapperIfUndefined, dataConvert) {
1008
+ switch (templateResult) {
1009
+ case SelectResult.R_C_NotSure: {
1010
+ try {
1011
+ if (dataConvert) {
1012
+ const key = Object.keys(result[0])[0];
1013
+ const value = Object.values(result[0])[0];
1014
+ if (key && dataConvert[key] && globalThis[_DataConvert][dataConvert[key]]) {
1015
+ return globalThis[_DataConvert][dataConvert[key]](value);
1016
+ }
1017
+ }
1018
+ return Object.values(result[0])[0];
1019
+ }
1020
+ catch (error) {
1021
+ return def;
1022
+ }
1023
+ }
1024
+ case SelectResult.R_C_Assert: {
1025
+ try {
1026
+ if (dataConvert) {
1027
+ const key = Object.keys(result[0])[0];
1028
+ const value = Object.values(result[0])[0];
1029
+ if (key && dataConvert[key] && globalThis[_DataConvert][dataConvert[key]]) {
1030
+ return globalThis[_DataConvert][dataConvert[key]](value);
1031
+ }
1032
+ }
1033
+ return Object.values(result[0])[0];
1034
+ }
1035
+ catch (error) {
1036
+ if (def !== undefined)
1037
+ return def;
1038
+ Throw.now(errorMsg ?? 'not found data!');
1039
+ }
1040
+ }
1041
+ case SelectResult.R_CS_NotSure: {
1042
+ if (mapper) {
1043
+ return flatData({ data: result[0], mapper, mapperIfUndefined });
1044
+ }
1045
+ else {
1046
+ hump = hump === true || (hump === undefined && globalThis[_Hump] === true);
1047
+ const __dataConvert = dataConvert ? Object.fromEntries(Object.entries(dataConvert).map(([k, v]) => [k, globalThis[_DataConvert][v]])) : undefined;
1048
+ if (hump || __dataConvert) {
1049
+ return C2P2(result[0], hump, __dataConvert) ?? null;
1050
+ }
1051
+ else {
1052
+ return result[0] ?? null;
1053
+ }
1054
+ }
1055
+ }
1056
+ case SelectResult.R_CS_Assert: {
1057
+ const data = result[0];
1058
+ Throw.if(data === null || data === undefined, errorMsg ?? 'not found data!');
1059
+ if (mapper) {
1060
+ return flatData({ data, mapper, mapperIfUndefined });
1061
+ }
1062
+ else {
1063
+ hump = hump === true || (hump === undefined && globalThis[_Hump] === true);
1064
+ const __dataConvert = dataConvert ? Object.fromEntries(Object.entries(dataConvert).map(([k, v]) => [k, globalThis[_DataConvert][v]])) : undefined;
1065
+ if (hump || __dataConvert) {
1066
+ return C2P2(data, hump, __dataConvert) ?? null;
1067
+ }
1068
+ else {
1069
+ return data;
1070
+ }
1071
+ }
1072
+ }
1073
+ case SelectResult.RS_C: {
1074
+ try {
1075
+ if (dataConvert) {
1076
+ const key = Object.keys(result[0])[0];
1077
+ if (key && dataConvert[key] && globalThis[_DataConvert][dataConvert[key]]) {
1078
+ return result.map((r) => globalThis[_DataConvert][dataConvert[key]](Object.values(r)[0]));
1079
+ }
1080
+ }
1081
+ return result.map((r) => Object.values(r)[0]);
1082
+ }
1083
+ catch (error) {
1084
+ return result;
1085
+ }
1086
+ }
1087
+ case SelectResult.RS_CS: {
1088
+ if (mapper) {
1089
+ return iterate(result).map((data) => flatData({ data, mapper, mapperIfUndefined })).toArray();
1090
+ }
1091
+ else {
1092
+ hump = hump === true || (hump === undefined && globalThis[_Hump] === true);
1093
+ const __dataConvert = dataConvert ? Object.fromEntries(Object.entries(dataConvert).map(([k, v]) => [k, globalThis[_DataConvert][v]])) : undefined;
1094
+ if (hump || __dataConvert) {
1095
+ return iterate(result).map((r) => C2P2(r, hump, __dataConvert)).toArray();
1096
+ }
1097
+ else {
1098
+ return result;
1099
+ }
1100
+ }
1101
+ }
1102
+ }
1103
+ }
1104
+ select(option) {
1105
+ Throw.if(!option.sqlId && !option.sql, 'not found sql!');
1106
+ option.selectResult ?? (option.selectResult = SelectResult.RS_CS);
1107
+ option.defValue ?? (option.defValue = null);
1108
+ if (option.sqlId && globalThis[_resultMap_SQLID][option.sqlId] && !option.mapper) {
1109
+ option.mapper = globalThis[_resultMap_SQLID][option.sqlId];
1110
+ }
1111
+ const _params = Object.assign({}, option.params);
1112
+ option.sql ?? (option.sql = globalThis[_sqlCache].load(this._matchSqlid(option.sqlId), { ctx: Object.assign({}, option.context, globalThis[_Context]), isCount: option.isCount, ..._params }));
1113
+ const { sql, params } = this._generSql(option.dbType, option.sql, _params);
1114
+ if (option.sync === SyncMode.Sync) {
1115
+ const result = option.conn.query(SyncMode.Sync, sql, params);
1116
+ return this._select(option.selectResult, result, option.defValue, option.errorMsg, option.hump, option.mapper, option.mapperIfUndefined, option.dataConvert);
1117
+ }
1118
+ else {
1119
+ return (async () => {
1120
+ const result = await option.conn.query(SyncMode.Async, sql, params);
1121
+ return this._select(option.selectResult, result, option.defValue, option.errorMsg, option.hump, option.mapper, option.mapperIfUndefined, option.dataConvert);
1122
+ })();
1123
+ }
1124
+ }
1125
+ selectBatch(option) {
1126
+ Throw.if(!option.sqlId && !option.sql, 'not found sql!');
1127
+ option.selectResult ?? (option.selectResult = SelectResult.RS_CS);
1128
+ if (option.sqlId && globalThis[_resultMap_SQLID][option.sqlId] && !option.mapper) {
1129
+ option.mapper = globalThis[_resultMap_SQLID][option.sqlId];
1130
+ }
1131
+ const _params = Object.assign({}, option.params);
1132
+ option.sql ?? (option.sql = globalThis[_sqlCache].load(this._matchSqlid(option.sqlId), { ctx: Object.assign({}, option.context, globalThis[_Context]), isCount: false, ..._params }));
1133
+ const { sql, params } = this._generSql(option.dbType, option.sql, _params);
1134
+ if (option.sync === SyncMode.Sync) {
1135
+ const result = option.conn.query(SyncMode.Sync, sql, params);
1136
+ return result.map(item => this._select(option.selectResult, item, null, undefined, option.hump, option.mapper, option.mapperIfUndefined, option.dataConvert));
1137
+ }
1138
+ else {
1139
+ return (async () => {
1140
+ const result = await option.conn.query(SyncMode.Async, sql, params);
1141
+ return result.map(item => this._select(option.selectResult, item, null, undefined, option.hump, option.mapper, option.mapperIfUndefined, option.dataConvert));
1142
+ })();
1143
+ }
1144
+ }
1145
+ excute(option) {
1146
+ Throw.if(!option.sqlId && !option.sql, 'not found sql!');
1147
+ const _params = Object.assign({}, option.params);
1148
+ option.sql ?? (option.sql = globalThis[_sqlCache].load(this._matchSqlid(option.sqlId), { ctx: Object.assign({}, option.context, globalThis[_Context]), ..._params }));
1149
+ const { sql, params } = this._generSql(option.dbType, option.sql, _params);
1150
+ if (option.sync === SyncMode.Sync) {
1151
+ const result = option.conn.execute(SyncMode.Sync, sql, params);
1152
+ return result.affectedRows;
1153
+ }
1154
+ else {
1155
+ return (async () => {
1156
+ const result = await option.conn.execute(SyncMode.Async, sql, params);
1157
+ return result.affectedRows;
1158
+ })();
1159
+ }
1160
+ }
1161
+ transaction(option) {
1162
+ if (option.sync === SyncMode.Sync) {
1163
+ return option.dao.transaction(SyncMode.Sync, option.fn, option.conn);
1164
+ }
1165
+ else {
1166
+ return option.dao.transaction(SyncMode.Async, option.fn, option.conn);
1167
+ }
1168
+ }
1169
+ stream() {
1170
+ return new StreamQuery(this, this[_fields], this[_columns]);
1171
+ }
1172
+ page(option) {
1173
+ const result = {
1174
+ sum: {},
1175
+ records: [],
1176
+ size: 0,
1177
+ total: 0
1178
+ };
1179
+ option.pageNumber ?? (option.pageNumber = 1);
1180
+ option.pageSize ?? (option.pageSize = 0);
1181
+ if (option.hump || (option.hump === undefined && globalThis[_Hump]) && option.sortName) {
1182
+ option.sortName = P2C(option.sortName);
1183
+ }
1184
+ // 不要 Object.assign 进调用方的 params——@P 装饰器对 option 只做了浅拷贝,
1185
+ // option.params 仍指向用户传入的对象,原写法会把分页字段写回去污染下一次调用。
1186
+ option.params = Object.assign({}, option.params, {
1187
+ limitStart: calc(option.pageNumber).sub(1).mul(option.pageSize).over(),
1188
+ limitEnd: option.pageSize - 0,
1189
+ sortName: option.sortName ?? undefined,
1190
+ sortType: option.sortType ?? undefined
1191
+ });
1192
+ const ctx = Object.assign({}, option.context, globalThis[_Context]);
1193
+ let sql = globalThis[_sqlCache].load(this._matchSqlid(option.sqlId), { ctx, isCount: false, ...option.params });
1194
+ let sqlSum = '';
1195
+ let sqlCount = '';
1196
+ if (option.sum) {
1197
+ if (option.sumSelf) {
1198
+ sqlCount = globalThis[_sqlCache].load(this._matchSqlid(`${option.sqlId}_sum`), { ctx, isCount: false, isSum: true, ...option.params });
1199
+ }
1200
+ else {
1201
+ sqlSum = globalThis[_sqlCache].load(this._matchSqlid(option.sqlId), { ctx, isCount: false, isSum: true, ...option.params });
1202
+ }
1203
+ }
1204
+ if (option.limitSelf !== true && option.pageSize > 0) {
1205
+ sql = `${sql} LIMIT ${option.params['limitStart']}, ${option.pageSize}`;
1206
+ }
1207
+ if (option.pageSize > 0) {
1208
+ if (option.countSelf) {
1209
+ sqlCount = globalThis[_sqlCache].load(this._matchSqlid(`${option.sqlId}_count`), { ctx, isCount: true, isSum: false, ...option.params });
1210
+ }
1211
+ else {
1212
+ sqlCount = globalThis[_sqlCache].load(this._matchSqlid(option.sqlId), { ctx, isCount: true, isSum: false, ...option.params });
1213
+ }
1214
+ }
1215
+ if (option.sync === SyncMode.Sync) {
1216
+ if (sqlCount) {
1217
+ result.total = this.select({
1218
+ ...option,
1219
+ sql: sqlCount,
1220
+ sync: SyncMode.Sync,
1221
+ selectResult: SelectResult.R_C_Assert
1222
+ });
1223
+ result.size = calc(result.total)
1224
+ .add(option.pageSize - 1)
1225
+ .div(option.pageSize)
1226
+ .round(0, 2)
1227
+ .over();
1228
+ }
1229
+ if (sqlSum) {
1230
+ result.sum = this.select({
1231
+ ...option,
1232
+ sql: sqlSum,
1233
+ sync: SyncMode.Sync,
1234
+ selectResult: SelectResult.R_CS_Assert
1235
+ });
1236
+ }
1237
+ if (sql) {
1238
+ result.records = this.select({
1239
+ ...option,
1240
+ sql,
1241
+ sync: SyncMode.Sync,
1242
+ selectResult: SelectResult.RS_CS
1243
+ });
1244
+ }
1245
+ return result;
1246
+ }
1247
+ else {
1248
+ return (async () => {
1249
+ if (sqlCount) {
1250
+ result.total = await this.select({
1251
+ ...option,
1252
+ sql: sqlCount,
1253
+ sync: SyncMode.Async,
1254
+ selectResult: SelectResult.R_C_Assert
1255
+ });
1256
+ // 修正运算符优先级:`option.pageSize ?? 10 - 1` 被解析为 `pageSize ?? 9`,
1257
+ // 而同步分支用的是 `option.pageSize - 1`,行为不一致。
1258
+ result.size = calc(result.total)
1259
+ .add((option.pageSize ?? 10) - 1)
1260
+ .div(option.pageSize)
1261
+ .round(0, 2)
1262
+ .over();
1263
+ }
1264
+ if (sqlSum) {
1265
+ result.sum = await this.select({
1266
+ ...option,
1267
+ sql: sqlSum,
1268
+ sync: SyncMode.Async,
1269
+ selectResult: SelectResult.R_CS_Assert
1270
+ });
1271
+ }
1272
+ if (sql) {
1273
+ result.records = await this.select({
1274
+ ...option,
1275
+ sql,
1276
+ sync: SyncMode.Async,
1277
+ selectResult: SelectResult.RS_CS
1278
+ });
1279
+ }
1280
+ return result;
1281
+ })();
1282
+ }
1283
+ }
1284
+ /**
1285
+ * 导出数据,可以为EJS-EXCEL直接使用
1286
+ * @param list
1287
+ * @returns
1288
+ */
1289
+ exp(list) {
1290
+ Throw.if(list.length === 0, 'not found data!');
1291
+ const columnTitles = new Array();
1292
+ const keys = this[_fields] ?
1293
+ iterate(Object.entries(this[_fields]))
1294
+ .filter(([K, F]) => (F.id !== true && F.exportable !== false) || (F.id === true && F.exportable === true))
1295
+ .map(([K, F]) => {
1296
+ columnTitles.push(F.comment ?? K);
1297
+ return K;
1298
+ }).toArray()
1299
+ : Object.keys(list[0]).filter(K => !this[_ids]?.includes(K));
1300
+ const title = this[_comment] ?? this[_tableName];
1301
+ const titleSpan = `A1:${ten2Any(keys.length)}1`;
1302
+ const datas = list.map(data => keys.map(k => data[k] ?? ''));
1303
+ return { title, titleSpan, columnTitles, datas };
1304
+ }
1305
+ /**
1306
+ * 导入数据的模板
1307
+ * @returns
1308
+ */
1309
+ imp() {
1310
+ Throw.if(!this[_fields], 'not set fields!');
1311
+ const columnTitles = new Array();
1312
+ const keys = iterate(Object.entries(this[_fields]))
1313
+ .filter(([K, F]) => (F.id !== true && F.exportable !== false) || (F.id === true && F.exportable === true))
1314
+ .map(([K, F]) => {
1315
+ columnTitles.push(F.comment ?? K);
1316
+ return K;
1317
+ }).toArray();
1318
+ const title = this[_comment] ?? this[_tableName];
1319
+ const titleSpan = `A1:${ten2Any(keys.length)}1`;
1320
+ return { title, titleSpan, columnTitles };
1321
+ }
1322
+ init(option) {
1323
+ var _a;
1324
+ const tableES = option.tableName;
1325
+ (_a = option).force ?? (_a.force = false);
1326
+ if (option.dbType === DBType.Sqlite) {
1327
+ if (option?.force) {
1328
+ option.conn.execute(SyncMode.Sync, `DROP TABLE IF EXISTS ${tableES};`);
1329
+ }
1330
+ const lastVersion = this[_sqlite_version] ?? '1';
1331
+ // 检查表
1332
+ const tableCheckResult = option.conn.pluck(SyncMode.Sync, `SELECT COUNT(1) t FROM sqlite_master WHERE TYPE = 'table' AND name = ?`, [option.tableName]);
1333
+ if (tableCheckResult) {
1334
+ // 旧版本
1335
+ const tableVersion = option.conn.pluck(SyncMode.Sync, 'SELECT ______version v from TABLE_VERSION WHERE ______tableName = ?', [option.tableName]);
1336
+ if (tableVersion && tableVersion < lastVersion) { // 发现需要升级的版本
1337
+ // 更新版本
1338
+ const columns = iterate(option.conn.query(SyncMode.Sync, `PRAGMA table_info(${tableES})`))
1339
+ .filter(c => this[_fields].hasOwnProperty(C2P(c.name, globalThis[_Hump])))
1340
+ .map(c => c.name)
1341
+ .join(',');
1342
+ const rtable = `${option.tableName}_${tableVersion.replace(/\./, '_')}`;
1343
+ option.conn.execute(SyncMode.Sync, `DROP TABLE IF EXISTS ${rtable};`);
1344
+ option.conn.execute(SyncMode.Sync, `ALTER TABLE ${tableES} RENAME TO ${rtable};`);
1345
+ option.conn.execute(SyncMode.Sync, `
1346
+ CREATE TABLE IF NOT EXISTS ${tableES}(
1347
+ ${Object.values(this[_fields]).map(K => K[DBType.Sqlite]()).join(',')}
1348
+ ${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields][i]?.C2()).join(',')})` : ''}
1349
+ );
1350
+ `);
1351
+ if (this[_index] && this[_index].length) {
1352
+ for (const index of this[_index]) {
1353
+ option.conn.execute(SyncMode.Sync, `CREATE INDEX ${`${index}_${Math.random()}`.replace(/\./, '')} ON ${tableES} ("${this[_fields][index]?.C2()}");`);
1354
+ }
1355
+ }
1356
+ option.conn.execute(SyncMode.Sync, `INSERT INTO ${tableES} (${columns}) SELECT ${columns} FROM ${rtable};`);
1357
+ option.conn.execute(SyncMode.Sync, `DROP TABLE IF EXISTS ${rtable};`);
1358
+ // 更新完毕,保存版本号
1359
+ option.conn.execute(SyncMode.Sync, 'UPDATE TABLE_VERSION SET ______version = ? WHERE ______tableName = ?', [option.tableName, lastVersion]);
1360
+ }
1361
+ else if (!tableVersion) { // 不需要升级情况:没有旧的版本号
1362
+ option.conn.execute(SyncMode.Sync, 'INSERT INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option.tableName, lastVersion]);
1363
+ }
1364
+ }
1365
+ else { // 表不存在
1366
+ // 创建表
1367
+ option.conn.execute(SyncMode.Sync, `
1368
+ CREATE TABLE IF NOT EXISTS ${tableES} (
1369
+ ${Object.values(this[_fields]).map(K => K[DBType.Sqlite]()).join(',')}
1370
+ ${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields][i]?.C2()).join(',')})` : ''}
1371
+
1372
+ );
1373
+ `);
1374
+ if (this[_index] && this[_index].length) {
1375
+ for (const index of this[_index]) {
1376
+ option.conn.execute(SyncMode.Sync, `CREATE INDEX ${`${index}_${Math.random()}`.replace(/\./, '')} ON ${tableES} ("${this[_fields][index]?.C2()}");`);
1377
+ }
1378
+ }
1379
+ option.conn.execute(SyncMode.Sync, 'INSERT OR REPLACE INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option.tableName, lastVersion]);
1380
+ }
1381
+ }
1382
+ else if (option.dbType === DBType.SqliteRemote) {
1383
+ return (async () => {
1384
+ if (option?.force) {
1385
+ await option.conn.execute(SyncMode.Async, `DROP TABLE IF EXISTS ${tableES};`);
1386
+ }
1387
+ const lastVersion = this[_sqlite_version] ?? '1';
1388
+ // 检查表
1389
+ const tableCheckResult = await option.conn.pluck(SyncMode.Async, `SELECT COUNT(1) t FROM sqlite_master WHERE TYPE = 'table' AND name = ?`, [option.tableName]);
1390
+ if (tableCheckResult) {
1391
+ // 旧版本
1392
+ const tableVersion = await option.conn.pluck(SyncMode.Async, 'SELECT ______version v from TABLE_VERSION WHERE ______tableName = ?', [option.tableName]);
1393
+ if (tableVersion && tableVersion < lastVersion) { // 发现需要升级的版本
1394
+ // 更新版本
1395
+ const columns = iterate(await option.conn.query(SyncMode.Async, `PRAGMA table_info(${tableES})`))
1396
+ .filter(c => this[_fields].hasOwnProperty(C2P(c.name, globalThis[_Hump])))
1397
+ .map(c => c.name)
1398
+ .join(',');
1399
+ const rtable = `${option.tableName}_${tableVersion.replace(/\./, '_')}`;
1400
+ await option.conn.execute(SyncMode.Async, `DROP TABLE IF EXISTS ${rtable};`);
1401
+ await option.conn.execute(SyncMode.Async, `ALTER TABLE ${tableES} RENAME TO ${rtable};`);
1402
+ await option.conn.execute(SyncMode.Async, `
1403
+ CREATE TABLE IF NOT EXISTS ${tableES}(
1404
+ ${Object.values(this[_fields]).map(K => K[DBType.Sqlite]()).join(',')}
1405
+ ${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields][i]?.C2()).join(',')})` : ''}
1406
+ );
1407
+ `);
1408
+ if (this[_index] && this[_index].length) {
1409
+ for (const index of this[_index]) {
1410
+ await option.conn.execute(SyncMode.Async, `CREATE INDEX ${`${index}_${Math.random()}`.replace(/\./, '')} ON ${tableES} ("${this[_fields][index]?.C2()}");`);
1411
+ }
1412
+ }
1413
+ await option.conn.execute(SyncMode.Async, `INSERT INTO ${tableES} (${columns}) SELECT ${columns} FROM ${rtable};`);
1414
+ await option.conn.execute(SyncMode.Async, `DROP TABLE IF EXISTS ${rtable};`);
1415
+ // 更新完毕,保存版本号
1416
+ await option.conn.execute(SyncMode.Async, 'UPDATE TABLE_VERSION SET ______version = ? WHERE ______tableName = ?', [option.tableName, lastVersion]);
1417
+ }
1418
+ else if (!tableVersion) { // 不需要升级情况:没有旧的版本号
1419
+ await option.conn.execute(SyncMode.Async, 'INSERT INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option.tableName, lastVersion]);
1420
+ }
1421
+ }
1422
+ else { // 表不存在
1423
+ // 创建表
1424
+ await option.conn.execute(SyncMode.Async, `
1425
+ CREATE TABLE IF NOT EXISTS ${tableES}(
1426
+ ${Object.values(this[_fields]).map(K => K[DBType.Sqlite]()).join(',')}
1427
+ ${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields][i]?.C2()).join(',')})` : ''}
1428
+ );
1429
+ `);
1430
+ if (this[_index] && this[_index].length) {
1431
+ for (const index of this[_index]) {
1432
+ await option.conn.execute(SyncMode.Async, `CREATE INDEX ${`${index}_${Math.random()}`.replace(/\./, '')} ON ${option.tableName} ("${this[_fields][index]?.C2()}");`);
1433
+ }
1434
+ }
1435
+ await option.conn.execute(SyncMode.Async, 'INSERT OR REPLACE INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option.tableName, lastVersion]);
1436
+ }
1437
+ })();
1438
+ }
1439
+ }
1440
+ close(option) {
1441
+ delete globalThis[_dao][option.dbType][option.dbName];
1442
+ if (option?.sync === SyncMode.Async) {
1443
+ return option.dao.close(SyncMode.Async);
1444
+ }
1445
+ else if (option?.sync === SyncMode.Sync) {
1446
+ option.dao.close(SyncMode.Sync);
1447
+ }
1448
+ }
1449
+ /**
1450
+ #创建表
1451
+ ** `tableName` 表名称
1452
+ ** `temp` 是否是临时表,默认true
1453
+ ** `columns` 字符串数组,默认是当前实体类全部字段,通过`columns` 可以创建部分字段临时表
1454
+ ** `id` 表的主键设置 4种:
1455
+ 1. `auto`: `columns`中已经在当前实体类配置的ID作为主键 `默认`
1456
+ 2. `all`: `columns`中所有字段全部当主键
1457
+ 3. `none`: 没有主键
1458
+ 4. 自定义字段名称:字符串数组
1459
+ ** `index` 表的索引,设置方式同ID
1460
+ */
1461
+ _createTable({ tableName, temp = true, columns, data, id = 'auto', index = 'auto', dbType } = {}) {
1462
+ const sqls = [];
1463
+ columns = columns || this[_columns];
1464
+ let ids;
1465
+ if (id === 'auto') {
1466
+ ids = this[_ids]?.filter(i => columns?.includes(i));
1467
+ }
1468
+ else if (id === 'all') {
1469
+ ids = columns;
1470
+ }
1471
+ else if (id === 'none') {
1472
+ ids = undefined;
1473
+ }
1474
+ else {
1475
+ ids = id;
1476
+ }
1477
+ let indexs;
1478
+ if (index === 'auto') {
1479
+ indexs = this[_index]?.filter(i => columns?.includes(i));
1480
+ }
1481
+ else if (index === 'all') {
1482
+ indexs = columns;
1483
+ }
1484
+ else if (index === 'none') {
1485
+ indexs = undefined;
1486
+ }
1487
+ else {
1488
+ indexs = index;
1489
+ }
1490
+ tableName = tableName ?? this[_tableName];
1491
+ switch (dbType) {
1492
+ case DBType.Mysql: {
1493
+ let sql = formatDialect(`CREATE ${temp ? 'TEMPORARY' : ''} TABLE IF NOT EXISTS ${tableName}(
1494
+ ${columns.map(K => this[_fields][K][DBType.Mysql]()).join(',')}
1495
+ ${ids && ids.length ? `,PRIMARY KEY (${ids.map(i => this[_fields][i]?.C2()).join(',')}) USING BTREE ` : ''}
1496
+ ${indexs && indexs.length ? `,${indexs.map(i => `KEY ${this[_fields][i]?.C2()} (${this[_fields][i]?.C2()})`).join(',')} ` : ''}
1497
+ ) ENGINE=MEMORY;`, { dialect: mysql });
1498
+ sqls.push({ sql });
1499
+ if (data && data.length > 0) {
1500
+ const params = [];
1501
+ let first = true;
1502
+ sql = formatDialect(`INSERT INTO ${tableName} (${columns.map(c => this[_fields][c]?.C2()).join(',')})
1503
+ ${(data).map(d => {
1504
+ const r = `SELECT ${Object.entries(d).map(([K, V]) => {
1505
+ params.push(V);
1506
+ return `? ${first ? this[_fields][K]?.C2() : ''}`;
1507
+ }).join(',')}`;
1508
+ first = false;
1509
+ return r;
1510
+ }).join(' UNION ALL ')}`, { dialect: mysql });
1511
+ sqls.push({ sql, params });
1512
+ }
1513
+ break;
1514
+ }
1515
+ case DBType.Sqlite:
1516
+ case DBType.SqliteRemote: {
1517
+ let sql = formatDialect(`CREATE ${temp ? 'TEMPORARY' : ''} TABLE IF NOT EXISTS ${tableName}(
1518
+ ${columns.map(K => this[_fields][K][DBType.Sqlite]()).join(',')}
1519
+ ${ids && ids.length ? `,PRIMARY KEY (${ids.map(i => this[_fields][i]?.C2()).join(',')}) ` : ''}
1520
+ );`, { dialect: sqlite });
1521
+ sqls.push({ sql });
1522
+ if (indexs) {
1523
+ for (const index of indexs) {
1524
+ sql = formatDialect(`CREATE INDEX ${`${index}_${Math.random()}`.replace(/\./, '')} ON ${tableName} (${this[_fields][index]?.C2()});`, { dialect: sqlite });
1525
+ sqls.push({ sql });
1526
+ }
1527
+ }
1528
+ if (data && data.length > 0) {
1529
+ const params = [];
1530
+ let first = true;
1531
+ sql = formatDialect(`INSERT INTO ${tableName} (${columns.map(c => this[_fields][c]?.C2()).join(',')})
1532
+ ${(data).map(d => {
1533
+ const r = `SELECT ${Object.entries(d).map(([K, V]) => {
1534
+ params.push(V);
1535
+ return `? ${first ? this[_fields][K]?.C2() : ''}`;
1536
+ }).join(',')}`;
1537
+ first = false;
1538
+ return r;
1539
+ }).join(' UNION ALL ')}`, { dialect: sqlite });
1540
+ sqls.push({ sql, params });
1541
+ }
1542
+ break;
1543
+ }
1544
+ }
1545
+ return sqls;
1546
+ }
1547
+ _matchSqlid(sqlid) {
1548
+ sqlid ?? (sqlid = '');
1549
+ if (sqlid.includes('.'))
1550
+ return [sqlid];
1551
+ else
1552
+ return [`${this[_tableName]}.${sqlid}`, `${this[_className]}.${sqlid}`, `${this[_ClassName]}.${sqlid}`, `${this[_vueName]}.${sqlid}`];
1553
+ }
1554
+ _setParam(v, ps) {
1555
+ if (v instanceof Array) {
1556
+ ps.push(...v);
1557
+ return v.map(i => '?').join(',');
1558
+ }
1559
+ else {
1560
+ ps.push(v);
1561
+ return '?';
1562
+ }
1563
+ }
1564
+ _generSql(dbType, _sql, _params) {
1565
+ const params = [];
1566
+ const sql = formatDialect(_sql?.replace(/\:([\w.]+)/g, (txt, key) => {
1567
+ let V = LGet(_params, key);
1568
+ if (V !== undefined) {
1569
+ return this._setParam(V, params);
1570
+ }
1571
+ const _key = C2P(key);
1572
+ V = LGet(_params, _key);
1573
+ if (V !== undefined) {
1574
+ return this._setParam(V, params);
1575
+ }
1576
+ const __key = P2C(key);
1577
+ V = LGet(_params, __key);
1578
+ if (V !== undefined) {
1579
+ return this._setParam(V, params);
1580
+ }
1581
+ return txt;
1582
+ }), { dialect: formatDialects[dbType] });
1583
+ return { params, sql };
1584
+ }
1585
+ }
1586
+ __decorate([
1587
+ P(),
1588
+ __metadata("design:type", Function),
1589
+ __metadata("design:paramtypes", [Object]),
1590
+ __metadata("design:returntype", Object)
1591
+ ], SqlService.prototype, "insert", null);
1592
+ __decorate([
1593
+ P(),
1594
+ __metadata("design:type", Function),
1595
+ __metadata("design:paramtypes", [Object]),
1596
+ __metadata("design:returntype", Object)
1597
+ ], SqlService.prototype, "update", null);
1598
+ __decorate([
1599
+ P(),
1600
+ __metadata("design:type", Function),
1601
+ __metadata("design:paramtypes", [Object]),
1602
+ __metadata("design:returntype", Object)
1603
+ ], SqlService.prototype, "delete", null);
1604
+ __decorate([
1605
+ P(),
1606
+ __metadata("design:type", Function),
1607
+ __metadata("design:paramtypes", [Object]),
1608
+ __metadata("design:returntype", Object)
1609
+ ], SqlService.prototype, "template", null);
1610
+ __decorate([
1611
+ P(),
1612
+ __metadata("design:type", Function),
1613
+ __metadata("design:paramtypes", [Object]),
1614
+ __metadata("design:returntype", Object)
1615
+ ], SqlService.prototype, "select", null);
1616
+ __decorate([
1617
+ P(),
1618
+ __metadata("design:type", Function),
1619
+ __metadata("design:paramtypes", [Object]),
1620
+ __metadata("design:returntype", Object)
1621
+ ], SqlService.prototype, "selectBatch", null);
1622
+ __decorate([
1623
+ P(),
1624
+ __metadata("design:type", Function),
1625
+ __metadata("design:paramtypes", [Object]),
1626
+ __metadata("design:returntype", Object)
1627
+ ], SqlService.prototype, "excute", null);
1628
+ __decorate([
1629
+ P(true),
1630
+ __metadata("design:type", Function),
1631
+ __metadata("design:paramtypes", [Object]),
1632
+ __metadata("design:returntype", Object)
1633
+ ], SqlService.prototype, "transaction", null);
1634
+ __decorate([
1635
+ P(),
1636
+ __metadata("design:type", Function),
1637
+ __metadata("design:paramtypes", [Object]),
1638
+ __metadata("design:returntype", Object)
1639
+ ], SqlService.prototype, "page", null);
1640
+ __decorate([
1641
+ P(),
1642
+ __metadata("design:type", Function),
1643
+ __metadata("design:paramtypes", [Object]),
1644
+ __metadata("design:returntype", Object)
1645
+ ], SqlService.prototype, "init", null);
1646
+ __decorate([
1647
+ P(),
1648
+ __metadata("design:type", Function),
1649
+ __metadata("design:paramtypes", [Object]),
1650
+ __metadata("design:returntype", Object)
1651
+ ], SqlService.prototype, "close", null);