baja-lite 1.0.7 → 1.0.16
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.
- package/cjs/boot-remote.js +4 -0
- package/cjs/boot.js +4 -0
- package/cjs/code.js +27 -12
- package/cjs/convert-xml.js +5 -1
- package/cjs/enum.d.ts +8 -0
- package/cjs/enum.js +33 -1
- package/cjs/fn.js +45 -35
- package/cjs/list.js +24 -0
- package/cjs/math.d.ts +14 -0
- package/cjs/math.js +39 -0
- package/cjs/set-ex.d.ts +8 -7
- package/cjs/set-ex.js +51 -58
- package/cjs/sql.d.ts +91 -34
- package/cjs/sql.js +382 -227
- package/cjs/sqlite.d.ts +5 -8
- package/cjs/sqlite.js +25 -22
- package/cjs/test-mysql.js +29 -21
- package/es/boot-remote.js +5 -1
- package/es/boot.js +5 -1
- package/es/code.js +27 -12
- package/es/convert-xml.js +2 -1
- package/es/enum.d.ts +8 -0
- package/es/enum.js +31 -0
- package/es/fn.js +45 -35
- package/es/list.js +24 -0
- package/es/math.d.ts +14 -0
- package/es/math.js +37 -0
- package/es/set-ex.d.ts +8 -7
- package/es/set-ex.js +48 -58
- package/es/sql.d.ts +91 -34
- package/es/sql.js +383 -228
- package/es/sqlite.d.ts +5 -8
- package/es/sqlite.js +26 -23
- package/es/test-mysql.js +30 -22
- package/package.json +70 -70
- package/src/boot-remote.ts +5 -1
- package/src/boot.ts +5 -1
- package/src/code.ts +45 -14
- package/src/convert-xml.ts +2 -2
- package/src/enum.ts +43 -3
- package/src/fn.ts +41 -33
- package/src/list.ts +27 -1
- package/src/math.ts +41 -3
- package/src/set-ex.ts +49 -58
- package/src/sql.ts +391 -217
- package/src/sqlite.ts +26 -20
- package/src/test-mysql.ts +30 -28
package/src/sql.ts
CHANGED
|
@@ -5,14 +5,42 @@ import iterare from 'iterare';
|
|
|
5
5
|
import { emptyString } from './string';
|
|
6
6
|
import pino from 'pino';
|
|
7
7
|
import { excuteSplit, ExcuteSplitMode, sleep } from './fn';
|
|
8
|
-
import { add, calc } from './math';
|
|
8
|
+
import { add, calc, ten2Any } from './math';
|
|
9
9
|
import mustache, { PartialsOrLookupFn } from 'mustache';
|
|
10
10
|
import { C2P, C2P2, P2C } from './object';
|
|
11
|
-
import {
|
|
11
|
+
import { formatDialect, sqlite, mysql, DialectOptions } from 'sql-formatter';
|
|
12
12
|
import HTML from 'html-parse-stringify';
|
|
13
13
|
import { XML, convert } from './convert-xml';
|
|
14
14
|
import { ArrayList } from './list';
|
|
15
15
|
import LGet from 'lodash.get';
|
|
16
|
+
import { EnumMap } from 'enum';
|
|
17
|
+
import { encode, decode, ExtensionCodec, DecodeError } from "@msgpack/msgpack";
|
|
18
|
+
(BigInt.prototype as any).toJSON = function () { return this.toString() }
|
|
19
|
+
|
|
20
|
+
const BIGINT_EXT_TYPE = 0;
|
|
21
|
+
export const extensionCodec = new ExtensionCodec();
|
|
22
|
+
extensionCodec.register({
|
|
23
|
+
type: BIGINT_EXT_TYPE,
|
|
24
|
+
encode(input: unknown): Uint8Array | null {
|
|
25
|
+
if (typeof input === "bigint") {
|
|
26
|
+
if (input <= Number.MAX_SAFE_INTEGER && input >= Number.MIN_SAFE_INTEGER) {
|
|
27
|
+
return encode(Number(input));
|
|
28
|
+
} else {
|
|
29
|
+
return encode(String(input));
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
decode(data: Uint8Array): bigint {
|
|
36
|
+
const val = decode(data);
|
|
37
|
+
if (!(typeof val === "string" || typeof val === "number")) {
|
|
38
|
+
throw new DecodeError(`unexpected BigInt source: ${val} (${typeof val})`);
|
|
39
|
+
}
|
|
40
|
+
return BigInt(val);
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
16
44
|
|
|
17
45
|
// #region 常量
|
|
18
46
|
const _daoDBName = Symbol('dbName');
|
|
@@ -21,6 +49,7 @@ const _className = Symbol('className');
|
|
|
21
49
|
const _ClassName = Symbol('ClassName');
|
|
22
50
|
const _vueName = Symbol('vueName');
|
|
23
51
|
const _ids = Symbol('ids');
|
|
52
|
+
const _logicIds = Symbol('logicIds');
|
|
24
53
|
const _columns = Symbol('columns');
|
|
25
54
|
const _columnsNoId = Symbol('columnsNoId');
|
|
26
55
|
const _fields = Symbol('fields');
|
|
@@ -29,10 +58,12 @@ const _deleteState = Symbol('deleteState');
|
|
|
29
58
|
const _transformer = Symbol('transformer');
|
|
30
59
|
const _index = Symbol('index');
|
|
31
60
|
const _def = Symbol('def');
|
|
61
|
+
const _comment = Symbol('comment');
|
|
32
62
|
export const _sqlCache = Symbol('sqlMap');
|
|
33
63
|
export const _dao = Symbol('dao');
|
|
34
64
|
export const _primaryDB = Symbol('primaryDB');
|
|
35
65
|
const _dbType = Symbol('dbType');
|
|
66
|
+
const _formatDialect = Symbol('FormatDialect');
|
|
36
67
|
const _sqlite_version = Symbol('sqlite_version');
|
|
37
68
|
const _daoConnection = Symbol('daoConnection');
|
|
38
69
|
const _inTransaction = Symbol('inTransaction');
|
|
@@ -41,6 +72,7 @@ const _sqliteRemoteName = Symbol('sqliteRemoteName');
|
|
|
41
72
|
const _SqlOption = Symbol('SqlOption');
|
|
42
73
|
const _resultMap = Symbol('resultMap');
|
|
43
74
|
const _resultMap_SQLID = Symbol('resultMap_SQLID');
|
|
75
|
+
export const _enums = Symbol('_enums');
|
|
44
76
|
export const _Hump = Symbol('Hump');
|
|
45
77
|
export const _GlobalSqlOption = Symbol('GlobalSqlOption');
|
|
46
78
|
export const _EventBus = Symbol('EventBus');
|
|
@@ -248,6 +280,8 @@ interface ServiceOption {
|
|
|
248
280
|
dbType?: DBType;
|
|
249
281
|
/** SQLite版本以及升级为该版本时需要执行的SQL,初始版本为0.0.1,切记每个位置不要变为两位数*/
|
|
250
282
|
sqliteVersion?: string;
|
|
283
|
+
/** 备注 */
|
|
284
|
+
comment?: string;
|
|
251
285
|
}
|
|
252
286
|
/**
|
|
253
287
|
# 全局行为配置文件
|
|
@@ -309,6 +343,23 @@ export interface GlobalSqlOptionForWeb {
|
|
|
309
343
|
]
|
|
310
344
|
*/
|
|
311
345
|
sqlMapperMap?: SqlMappers;
|
|
346
|
+
/** 提供的枚举MAP */
|
|
347
|
+
enums?: EnumMap;
|
|
348
|
+
/**
|
|
349
|
+
* `列名与属性映射` 是否自动将下划线转为驼峰,默认NONE,即不转.
|
|
350
|
+
* 当设置为columnMode.HUMP时,切记将代码生成器中属性名称改对
|
|
351
|
+
* # 自定义sql查询时,无法自动转换哦,可使用标签转换:
|
|
352
|
+
*```
|
|
353
|
+
SELECT
|
|
354
|
+
* {{#hump}} seller_sku2, seller_sku {{/hump}}
|
|
355
|
+
* ```
|
|
356
|
+
* 转换为
|
|
357
|
+
*```
|
|
358
|
+
SELECT
|
|
359
|
+
* {{#hump}} seller_sku2 sellerSku2, seller_sku sellerSku {{/hump}}
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
362
|
+
columnMode?: ColumnMode;
|
|
312
363
|
}
|
|
313
364
|
/**
|
|
314
365
|
# 全局行为配置文件
|
|
@@ -370,12 +421,13 @@ export interface GlobalSqlOption extends GlobalSqlOptionForWeb {
|
|
|
370
421
|
export default {
|
|
371
422
|
'sql_1': 'SELECT * FROM user WHERE username = :username',
|
|
372
423
|
'sql_2': (options: {
|
|
373
|
-
ctx
|
|
424
|
+
ctx?: any;
|
|
374
425
|
isCount?: boolean;
|
|
426
|
+
isSum?: boolean;
|
|
375
427
|
limitStart?: number;
|
|
376
428
|
limitEnd?: number;
|
|
377
429
|
orderBy?: string;
|
|
378
|
-
|
|
430
|
+
params?: Record<string, any>;
|
|
379
431
|
}) => {
|
|
380
432
|
return `
|
|
381
433
|
SELECT * FROM user u LEFT JOIN organ o ON u.orgid = o.orgid
|
|
@@ -442,21 +494,7 @@ export interface GlobalSqlOption extends GlobalSqlOptionForWeb {
|
|
|
442
494
|
*/
|
|
443
495
|
Redis?: Record<string, Record<string, any>> | Record<string, any>;
|
|
444
496
|
|
|
445
|
-
|
|
446
|
-
* `列名与属性映射` 是否自动将下划线转为驼峰,默认NONE,即不转.
|
|
447
|
-
* 当设置为columnMode.HUMP时,切记将代码生成器中属性名称改对
|
|
448
|
-
* # 自定义sql查询时,无法自动转换哦,可使用标签转换:
|
|
449
|
-
*```
|
|
450
|
-
SELECT
|
|
451
|
-
* {{#hump}} seller_sku2, seller_sku {{/hump}}
|
|
452
|
-
* ```
|
|
453
|
-
* 转换为
|
|
454
|
-
*```
|
|
455
|
-
SELECT
|
|
456
|
-
* {{#hump}} seller_sku2 sellerSku2, seller_sku sellerSku {{/hump}}
|
|
457
|
-
* ```
|
|
458
|
-
*/
|
|
459
|
-
columnMode?: ColumnMode;
|
|
497
|
+
|
|
460
498
|
/**
|
|
461
499
|
* 读取查询语句时,是否扫描JS文件?
|
|
462
500
|
* JS文件需要默认导出一个 SqlModel对象
|
|
@@ -474,9 +512,16 @@ interface FieldOption extends Object {
|
|
|
474
512
|
index?: boolean;
|
|
475
513
|
id?: boolean;
|
|
476
514
|
logicDelete?: string | number;
|
|
515
|
+
/** 是否逻辑唯一,用于导入时检测数据是否存在 */
|
|
516
|
+
logicId?: boolean;
|
|
477
517
|
/** 仅在生成 表时有效 */
|
|
478
518
|
notNull?: boolean;
|
|
519
|
+
/** 注释,影响到默认导出导入标题 */
|
|
479
520
|
comment?: string;
|
|
521
|
+
/** 可以导入的字段,默认TRUE,ID默认FALSE */
|
|
522
|
+
importable?: boolean;
|
|
523
|
+
/** 可以导出的字段,默认TRUE,ID默认FALSE */
|
|
524
|
+
exportable?: boolean;
|
|
480
525
|
/** sqlite 无效,与UUID只能有一个 */
|
|
481
526
|
uuidShort?: boolean;
|
|
482
527
|
/** 与uuidShort只能有一个 */
|
|
@@ -493,6 +538,7 @@ interface AField extends FieldOption {
|
|
|
493
538
|
[DBType.Mysql]: () => string;
|
|
494
539
|
[DBType.Sqlite]: () => string;
|
|
495
540
|
[DBType.SqliteRemote]: () => string;
|
|
541
|
+
Data2SQL: (data: any) => any;
|
|
496
542
|
}
|
|
497
543
|
export interface PageQuery<L> {
|
|
498
544
|
sum?: Record<string, number>;
|
|
@@ -505,12 +551,11 @@ export interface PageQuery<L> {
|
|
|
505
551
|
// #region 数据方言
|
|
506
552
|
/** sqlite electron服务端需要支持的接口 */
|
|
507
553
|
export interface SqliteRemoteInterface {
|
|
508
|
-
execute(
|
|
509
|
-
pluck
|
|
510
|
-
get
|
|
511
|
-
raw
|
|
512
|
-
query
|
|
513
|
-
|
|
554
|
+
execute(inData: Uint8Array): | Promise<Uint8Array>
|
|
555
|
+
pluck(inData: Uint8Array): Promise<Uint8Array>;
|
|
556
|
+
get(inData: Uint8Array): Promise<Uint8Array>;
|
|
557
|
+
raw(inData: Uint8Array): Promise<Uint8Array>;
|
|
558
|
+
query(inData: Uint8Array): Promise<Uint8Array>;
|
|
514
559
|
initDB(dbName: string): Promise<void>;
|
|
515
560
|
export(dbName: string): Promise<void>;
|
|
516
561
|
restore(dbName: string, fromName: string): Promise<void>;
|
|
@@ -1059,7 +1104,8 @@ export class SqliteRemoteConnection implements Connection {
|
|
|
1059
1104
|
}
|
|
1060
1105
|
return new Promise<{ affectedRows: number; insertId: bigint; }>(async (resolve, reject) => {
|
|
1061
1106
|
try {
|
|
1062
|
-
const
|
|
1107
|
+
const data = await this[_daoConnection].execute(encode([this[_sqliteRemoteName], sql, params], { extensionCodec }));
|
|
1108
|
+
const { affectedRows, insertId } = decode(data, { extensionCodec }) as { affectedRows: number; insertId: bigint; };
|
|
1063
1109
|
resolve({ affectedRows, insertId: insertId ? BigInt(insertId) : 0n });
|
|
1064
1110
|
} catch (error) {
|
|
1065
1111
|
logger.error(`
|
|
@@ -1086,7 +1132,8 @@ export class SqliteRemoteConnection implements Connection {
|
|
|
1086
1132
|
}
|
|
1087
1133
|
return new Promise<T | null>(async (resolve, reject) => {
|
|
1088
1134
|
try {
|
|
1089
|
-
const
|
|
1135
|
+
const data = await this[_daoConnection].pluck(encode([this[_sqliteRemoteName], sql, params], { extensionCodec }));
|
|
1136
|
+
const r = decode(data, { extensionCodec }) as T;
|
|
1090
1137
|
resolve(r);
|
|
1091
1138
|
} catch (error) {
|
|
1092
1139
|
logger.error(`
|
|
@@ -1113,7 +1160,8 @@ export class SqliteRemoteConnection implements Connection {
|
|
|
1113
1160
|
}
|
|
1114
1161
|
return new Promise<T | null>(async (resolve, reject) => {
|
|
1115
1162
|
try {
|
|
1116
|
-
const
|
|
1163
|
+
const data = await this[_daoConnection].get(encode([this[_sqliteRemoteName], sql, params], { extensionCodec }));
|
|
1164
|
+
const r = decode(data, { extensionCodec }) as T;
|
|
1117
1165
|
resolve(r);
|
|
1118
1166
|
} catch (error) {
|
|
1119
1167
|
logger.error(`
|
|
@@ -1140,7 +1188,8 @@ export class SqliteRemoteConnection implements Connection {
|
|
|
1140
1188
|
}
|
|
1141
1189
|
return new Promise<T[]>(async (resolve, reject) => {
|
|
1142
1190
|
try {
|
|
1143
|
-
const
|
|
1191
|
+
const data = await this[_daoConnection].raw(encode([this[_sqliteRemoteName], sql, params], { extensionCodec }));
|
|
1192
|
+
const r = decode(data, { extensionCodec }) as T[];
|
|
1144
1193
|
resolve(r);
|
|
1145
1194
|
} catch (error) {
|
|
1146
1195
|
logger.error(`
|
|
@@ -1167,7 +1216,8 @@ export class SqliteRemoteConnection implements Connection {
|
|
|
1167
1216
|
}
|
|
1168
1217
|
return new Promise<T[]>(async (resolve, reject) => {
|
|
1169
1218
|
try {
|
|
1170
|
-
const
|
|
1219
|
+
const data = await this[_daoConnection].query(encode([this[_sqliteRemoteName], sql, params], { extensionCodec }));
|
|
1220
|
+
const r = decode(data, { extensionCodec }) as T[];
|
|
1171
1221
|
resolve(r);
|
|
1172
1222
|
} catch (error) {
|
|
1173
1223
|
logger.error(`
|
|
@@ -1188,6 +1238,7 @@ export class SqliteRemoteConnection implements Connection {
|
|
|
1188
1238
|
export class SqliteRemote implements Dao {
|
|
1189
1239
|
[_sqliteRemoteName]: string;
|
|
1190
1240
|
[_daoDB]: SqliteRemoteInterface;
|
|
1241
|
+
private connection?: SqliteRemoteConnection;
|
|
1191
1242
|
|
|
1192
1243
|
constructor(db: SqliteRemoteInterface, name: string) {
|
|
1193
1244
|
this[_daoDB] = db;
|
|
@@ -1203,8 +1254,11 @@ export class SqliteRemote implements Dao {
|
|
|
1203
1254
|
return null;
|
|
1204
1255
|
};
|
|
1205
1256
|
return new Promise<Connection>(async (resolve, reject) => {
|
|
1257
|
+
if (!this.connection) {
|
|
1258
|
+
this.connection = new SqliteRemoteConnection(this[_daoDB], this[_sqliteRemoteName]);
|
|
1259
|
+
}
|
|
1206
1260
|
try {
|
|
1207
|
-
resolve(
|
|
1261
|
+
resolve(this.connection);
|
|
1208
1262
|
} catch (error) {
|
|
1209
1263
|
reject(error);
|
|
1210
1264
|
}
|
|
@@ -1282,24 +1336,24 @@ export type SqlMapper = ([string, string[], any?])[];
|
|
|
1282
1336
|
export type SqlMappers = Record<string, SqlMapper>;
|
|
1283
1337
|
export type SqlModel = Record<string, string | (
|
|
1284
1338
|
(options: {
|
|
1285
|
-
ctx
|
|
1339
|
+
ctx?: any;
|
|
1286
1340
|
isCount?: boolean;
|
|
1287
1341
|
isSum?: boolean;
|
|
1288
1342
|
limitStart?: number;
|
|
1289
1343
|
limitEnd?: number;
|
|
1290
1344
|
orderBy?: string;
|
|
1291
|
-
|
|
1345
|
+
params?: any;
|
|
1292
1346
|
}) => string
|
|
1293
1347
|
)>;
|
|
1294
1348
|
type _SqlModel = Record<string, string | (
|
|
1295
1349
|
(options: {
|
|
1296
|
-
ctx
|
|
1350
|
+
ctx?: any;
|
|
1297
1351
|
isCount?: boolean;
|
|
1298
1352
|
isSum?: boolean;
|
|
1299
1353
|
limitStart?: number;
|
|
1300
1354
|
limitEnd?: number;
|
|
1301
1355
|
orderBy?: string;
|
|
1302
|
-
|
|
1356
|
+
params?: any;
|
|
1303
1357
|
}) => string
|
|
1304
1358
|
) | XML[]>;
|
|
1305
1359
|
class Build {
|
|
@@ -1563,6 +1617,31 @@ class Build {
|
|
|
1563
1617
|
}
|
|
1564
1618
|
};
|
|
1565
1619
|
}
|
|
1620
|
+
/**
|
|
1621
|
+
* * PROBLEM_TYPE = 枚举名
|
|
1622
|
+
* * t.problemtype = 列名
|
|
1623
|
+
*
|
|
1624
|
+
* ```
|
|
1625
|
+
* {{#enumTag}} PROBLEM_TYPE(t.problemtype) {{/enumTag}}
|
|
1626
|
+
* ```
|
|
1627
|
+
*/
|
|
1628
|
+
enum() {
|
|
1629
|
+
return (text: string) => {
|
|
1630
|
+
const matchs = text.match(/([a-zA-Z_]+)\(([^()]+)\)/);
|
|
1631
|
+
if (matchs) {
|
|
1632
|
+
const [_a, MapName, Column] = matchs;
|
|
1633
|
+
if (MapName && Column) {
|
|
1634
|
+
const map = globalThis[_enums].GlobalMap[MapName.trim()];
|
|
1635
|
+
if (map) {
|
|
1636
|
+
return ` CASE
|
|
1637
|
+
${Object.entries(map).map(([k, v]) => `WHEN ${Column} = '${k}' THEN '${v}'`).join(' ')}
|
|
1638
|
+
END `;
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
return "''";
|
|
1643
|
+
};
|
|
1644
|
+
}
|
|
1566
1645
|
}
|
|
1567
1646
|
|
|
1568
1647
|
function replaceCdata(rawText: string) {
|
|
@@ -1767,7 +1846,7 @@ export class SqlCache {
|
|
|
1767
1846
|
}
|
|
1768
1847
|
}
|
|
1769
1848
|
load(sqlids: string[], options: {
|
|
1770
|
-
ctx
|
|
1849
|
+
ctx?: any;
|
|
1771
1850
|
isCount?: boolean;
|
|
1772
1851
|
isSum?: boolean;
|
|
1773
1852
|
limitStart?: number;
|
|
@@ -1787,17 +1866,12 @@ export class SqlCache {
|
|
|
1787
1866
|
const buildParam = new Build(options.isCount === true, options.isSum === true, options);
|
|
1788
1867
|
if (typeof sqlSource === 'function') {
|
|
1789
1868
|
const _sql = sqlSource(options);
|
|
1790
|
-
|
|
1791
|
-
return format(sql);
|
|
1869
|
+
return mustache.render(_sql, buildParam, this.sqlFNMap);
|
|
1792
1870
|
} else if (typeof sqlSource === 'string') {
|
|
1793
|
-
|
|
1794
|
-
return format(sql);
|
|
1871
|
+
return mustache.render(sqlSource, buildParam, this.sqlFNMap);
|
|
1795
1872
|
} else if (typeof sqlSource === 'object') {
|
|
1796
1873
|
const _sql = convert(sqlSource, options, matchSqlid, this.sqlMap as Record<string, XML[]>);
|
|
1797
|
-
|
|
1798
|
-
const sql = mustache.render(_sql, buildParam, this.sqlFNMap);
|
|
1799
|
-
console.log(sql);
|
|
1800
|
-
return format(sql);
|
|
1874
|
+
return mustache.render(_sql, buildParam, this.sqlFNMap);
|
|
1801
1875
|
}
|
|
1802
1876
|
return '';
|
|
1803
1877
|
}
|
|
@@ -1829,12 +1903,9 @@ function P<T extends object>(skipConn = false) {
|
|
|
1829
1903
|
const option = args[0] = Object.assign({}, globalThis[_GlobalSqlOption], this[_SqlOption], args[0]) as (MethodOption & { sync?: SyncMode; });
|
|
1830
1904
|
option.sync ??= SyncMode.Async;
|
|
1831
1905
|
const dbName = option?.dbName ?? this[_daoDBName] ?? _primaryDB;
|
|
1832
|
-
const dddx = this[_dbType];
|
|
1833
|
-
logger.info(dddx);
|
|
1834
1906
|
option!.dao = globalThis[_dao][this[_dbType]!][dbName] as Dao;
|
|
1835
1907
|
Throw.if(!option!.dao, `not found db:${String(dbName)}(${this[_dbType]})`);
|
|
1836
1908
|
option!.tableName = option?.tableName ?? this[_tableName];
|
|
1837
|
-
const tableES = Sqlstring.escapeId(option!.tableName);
|
|
1838
1909
|
if (this[_dbType] === DBType.Sqlite) {
|
|
1839
1910
|
Throw.if(option.sync === SyncMode.Async, 'sqlite can not Async!')
|
|
1840
1911
|
// 连接共享
|
|
@@ -1843,59 +1914,6 @@ function P<T extends object>(skipConn = false) {
|
|
|
1843
1914
|
} else {
|
|
1844
1915
|
needRealseConn = false;
|
|
1845
1916
|
}
|
|
1846
|
-
if (skipConn === false) {
|
|
1847
|
-
const lastVersion = this[_sqlite_version] ?? '0.0.1';
|
|
1848
|
-
// 检查表
|
|
1849
|
-
const tableCheckResult = option!.conn!.pluck<number>(SyncMode.Sync, `SELECT COUNT(1) t FROM sqlite_master WHERE TYPE = 'table' AND name = ?`, [option!.tableName]);
|
|
1850
|
-
if (tableCheckResult) {
|
|
1851
|
-
// 旧版本
|
|
1852
|
-
const tableVersion = option!.conn!.pluck<string>(SyncMode.Sync, 'SELECT ______version v from TABLE_VERSION WHERE ______tableName = ?', [option!.tableName]);
|
|
1853
|
-
if (tableVersion && tableVersion < lastVersion) { // 发现需要升级的版本
|
|
1854
|
-
// 更新版本
|
|
1855
|
-
const columns = iterare<{ name: string }>(option!.conn!.query(SyncMode.Sync, `PRAGMA table_info(${tableES})`))
|
|
1856
|
-
.filter(c => this[_fields]!.hasOwnProperty(C2P(c.name, globalThis[_Hump])))
|
|
1857
|
-
.map(c => Sqlstring.escapeId(c.name))
|
|
1858
|
-
.join(',');
|
|
1859
|
-
|
|
1860
|
-
const rtable = Sqlstring.escapeId(`${option!.tableName}_${tableVersion.replace(/\./, '_')}`);
|
|
1861
|
-
option!.conn!.execute(SyncMode.Sync, `DROP TABLE IF EXISTS ${rtable};`);
|
|
1862
|
-
option!.conn!.execute(SyncMode.Sync, `ALTER TABLE ${tableES} RENAME TO ${rtable};`);
|
|
1863
|
-
option!.conn!.execute(SyncMode.Sync, `
|
|
1864
|
-
CREATE TABLE IF NOT EXISTS ${tableES}(
|
|
1865
|
-
${Object.values(this[_fields]!).map(K => K[DBType.Sqlite]()).join(',')}
|
|
1866
|
-
${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields]![i]?.C2()).join(',')})` : ''}
|
|
1867
|
-
);
|
|
1868
|
-
`);
|
|
1869
|
-
if (this[_index] && this[_index].length) {
|
|
1870
|
-
for (const index of this[_index]) {
|
|
1871
|
-
option!.conn!.execute(SyncMode.Sync, `CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${tableES} ("${this[_fields]![index]?.C2()}");`);
|
|
1872
|
-
}
|
|
1873
|
-
}
|
|
1874
|
-
option!.conn!.execute(SyncMode.Sync, `INSERT INTO ${tableES} (${columns}) SELECT ${columns} FROM ${rtable};`);
|
|
1875
|
-
option!.conn!.execute(SyncMode.Sync, `INSERT INTO ${tableES} (${columns}) SELECT ${columns} FROM ${rtable};`);
|
|
1876
|
-
option!.conn!.execute(SyncMode.Sync, `DROP TABLE IF EXISTS ${rtable};`);
|
|
1877
|
-
// 更新完毕,保存版本号
|
|
1878
|
-
option!.conn!.execute(SyncMode.Sync, 'UPDATE TABLE_VERSION SET ______version = ? WHERE ______tableName = ?', [option!.tableName, lastVersion]);
|
|
1879
|
-
} else if (!tableVersion) { // 不需要升级情况:没有旧的版本号
|
|
1880
|
-
option!.conn!.execute(SyncMode.Sync, 'INSERT INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option!.tableName, lastVersion]);
|
|
1881
|
-
}
|
|
1882
|
-
} else { // 表不存在
|
|
1883
|
-
// 创建表
|
|
1884
|
-
option!.conn!.execute(SyncMode.Sync, `
|
|
1885
|
-
CREATE TABLE IF NOT EXISTS ${tableES} (
|
|
1886
|
-
${Object.values(this[_fields]!).map(K => K[DBType.Sqlite]()).join(',')}
|
|
1887
|
-
${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields]![i]?.C2()).join(',')})` : ''}
|
|
1888
|
-
|
|
1889
|
-
);
|
|
1890
|
-
`);
|
|
1891
|
-
if (this[_index] && this[_index].length) {
|
|
1892
|
-
for (const index of this[_index]) {
|
|
1893
|
-
option!.conn!.execute(SyncMode.Sync, `CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${tableES} ("${this[_fields]![index]?.C2()}");`);
|
|
1894
|
-
}
|
|
1895
|
-
}
|
|
1896
|
-
option!.conn!.execute(SyncMode.Sync, 'INSERT OR REPLACE INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option!.tableName, lastVersion]);
|
|
1897
|
-
}
|
|
1898
|
-
}
|
|
1899
1917
|
try {
|
|
1900
1918
|
const result = fn.call(this, ...args);
|
|
1901
1919
|
logger.info(`${propertyKey}:${option!.tableName}:use ${+new Date() - startTime}ms`);
|
|
@@ -1924,58 +1942,6 @@ function P<T extends object>(skipConn = false) {
|
|
|
1924
1942
|
} else {
|
|
1925
1943
|
needRealseConn = false;
|
|
1926
1944
|
}
|
|
1927
|
-
if (skipConn === false) {
|
|
1928
|
-
const lastVersion = this[_sqlite_version] ?? '0.0.1';
|
|
1929
|
-
// 检查表
|
|
1930
|
-
const tableCheckResult = await option!.conn!.pluck<number>(SyncMode.Async, `SELECT COUNT(1) t FROM sqlite_master WHERE TYPE = 'table' AND name = ?`, [option!.tableName]);
|
|
1931
|
-
if (tableCheckResult) {
|
|
1932
|
-
// 旧版本
|
|
1933
|
-
const tableVersion = await option!.conn!.pluck<string>(SyncMode.Async, 'SELECT ______version v from TABLE_VERSION WHERE ______tableName = ?', [option!.tableName]);
|
|
1934
|
-
if (tableVersion && tableVersion < lastVersion) { // 发现需要升级的版本
|
|
1935
|
-
// 更新版本
|
|
1936
|
-
const columns = iterare<{ name: string }>(await option!.conn!.query(SyncMode.Async, `PRAGMA table_info(${tableES})`))
|
|
1937
|
-
.filter(c => this[_fields]!.hasOwnProperty(C2P(c.name, globalThis[_Hump])))
|
|
1938
|
-
.map(c => Sqlstring.escapeId(c.name))
|
|
1939
|
-
.join(',');
|
|
1940
|
-
|
|
1941
|
-
const rtable = `${option!.tableName}_${tableVersion.replace(/\./, '_')}`;
|
|
1942
|
-
await option!.conn!.execute(SyncMode.Async, `DROP TABLE IF EXISTS ${rtable};`);
|
|
1943
|
-
await option!.conn!.execute(SyncMode.Async, `ALTER TABLE ${tableES} RENAME TO ${rtable};`);
|
|
1944
|
-
await option!.conn!.execute(SyncMode.Async, `
|
|
1945
|
-
CREATE TABLE IF NOT EXISTS ${tableES}(
|
|
1946
|
-
${Object.values(this[_fields]!).map(K => K[DBType.Sqlite]()).join(',')}
|
|
1947
|
-
${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields]![i]?.C2()).join(',')})` : ''}
|
|
1948
|
-
);
|
|
1949
|
-
`);
|
|
1950
|
-
if (this[_index] && this[_index].length) {
|
|
1951
|
-
for (const index of this[_index]) {
|
|
1952
|
-
await option!.conn!.execute(SyncMode.Async, `CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${tableES} ("${this[_fields]![index]?.C2()}");`);
|
|
1953
|
-
}
|
|
1954
|
-
}
|
|
1955
|
-
await option!.conn!.execute(SyncMode.Async, `INSERT INTO ${tableES} (${columns}) SELECT ${columns} FROM ${rtable};`);
|
|
1956
|
-
await option!.conn!.execute(SyncMode.Async, `INSERT INTO ${tableES} (${columns}) SELECT ${columns} FROM ${rtable};`);
|
|
1957
|
-
await option!.conn!.execute(SyncMode.Async, `DROP TABLE IF EXISTS ${rtable};`);
|
|
1958
|
-
// 更新完毕,保存版本号
|
|
1959
|
-
await option!.conn!.execute(SyncMode.Async, 'UPDATE TABLE_VERSION SET ______version = ? WHERE ______tableName = ?', [option!.tableName, lastVersion]);
|
|
1960
|
-
} else if (!tableVersion) { // 不需要升级情况:没有旧的版本号
|
|
1961
|
-
await option!.conn!.execute(SyncMode.Async, 'INSERT INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option!.tableName, lastVersion]);
|
|
1962
|
-
}
|
|
1963
|
-
} else { // 表不存在
|
|
1964
|
-
// 创建表
|
|
1965
|
-
await option!.conn!.execute(SyncMode.Async, `
|
|
1966
|
-
CREATE TABLE IF NOT EXISTS ${tableES}(
|
|
1967
|
-
${Object.values(this[_fields]!).map(K => K[DBType.Sqlite]()).join(',')}
|
|
1968
|
-
${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields]![i]?.C2()).join(',')})` : ''}
|
|
1969
|
-
);
|
|
1970
|
-
`);
|
|
1971
|
-
if (this[_index] && this[_index].length) {
|
|
1972
|
-
for (const index of this[_index]) {
|
|
1973
|
-
await option!.conn!.execute(SyncMode.Async, `CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${Sqlstring.escapeId(option!.tableName)} ("${this[_fields]![index]?.C2()}");`);
|
|
1974
|
-
}
|
|
1975
|
-
}
|
|
1976
|
-
await option!.conn!.execute(SyncMode.Async, 'INSERT OR REPLACE INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option!.tableName, lastVersion]);
|
|
1977
|
-
}
|
|
1978
|
-
}
|
|
1979
1945
|
try {
|
|
1980
1946
|
const result = await fn.call(this, ...args);
|
|
1981
1947
|
logger.info(`${propertyKey}:${option!.tableName}:use ${+new Date() - startTime}ms`);
|
|
@@ -2099,6 +2065,7 @@ export const Field = (config: FieldOption) => {
|
|
|
2099
2065
|
case SqlType.bigint: {
|
|
2100
2066
|
field[DBType.Mysql] = () => `${field.C2()} bigint ${config.notNull === true ? 'NOT NULL' : ''} ${MYSQLCHARSET} ${hasDef ? `DEFAULT '${field.def}'` : ''}`;
|
|
2101
2067
|
field[DBType.SqliteRemote] = field[DBType.Sqlite] = () => `${field.C2()} integer`;
|
|
2068
|
+
field.Data2SQL = (data: any) => BigInt(data ?? 0);
|
|
2102
2069
|
break;
|
|
2103
2070
|
}
|
|
2104
2071
|
case SqlType.float: {
|
|
@@ -2135,26 +2102,31 @@ export const Field = (config: FieldOption) => {
|
|
|
2135
2102
|
case SqlType.date: {
|
|
2136
2103
|
field[DBType.Mysql] = () => `${field.C2()} date ${config.notNull === true ? 'NOT NULL' : ''} ${MYSQLCHARSET} ${hasDef ? `DEFAULT '${field.def}'` : ''}`;
|
|
2137
2104
|
field[DBType.SqliteRemote] = field[DBType.Sqlite] = () => `${field.C2()} text`;
|
|
2105
|
+
field.Data2SQL = (data: any) => typeof data === 'string' ? new Date(data) : data;
|
|
2138
2106
|
break;
|
|
2139
2107
|
}
|
|
2140
2108
|
case SqlType.time: {
|
|
2141
2109
|
field[DBType.Mysql] = () => `${field.C2()} time ${config.notNull === true ? 'NOT NULL' : ''} ${MYSQLCHARSET} ${hasDef ? `DEFAULT '${field.def}'` : ''}`;
|
|
2142
2110
|
field[DBType.SqliteRemote] = field[DBType.Sqlite] = () => `${field.C2()} text`;
|
|
2111
|
+
field.Data2SQL = (data: any) => typeof data === 'string' ? new Date(data) : data;
|
|
2143
2112
|
break;
|
|
2144
2113
|
}
|
|
2145
2114
|
case SqlType.year: {
|
|
2146
2115
|
field[DBType.Mysql] = () => `${field.C2()} year ${config.notNull === true ? 'NOT NULL' : ''} ${MYSQLCHARSET} ${hasDef ? `DEFAULT '${field.def}'` : ''}`;
|
|
2147
2116
|
field[DBType.SqliteRemote] = field[DBType.Sqlite] = () => `${field.C2()} text`;
|
|
2117
|
+
field.Data2SQL = (data: any) => typeof data === 'string' ? new Date(data) : data;
|
|
2148
2118
|
break;
|
|
2149
2119
|
}
|
|
2150
2120
|
case SqlType.datetime: {
|
|
2151
2121
|
field[DBType.Mysql] = () => `${field.C2()} datetime ${config.notNull === true ? 'NOT NULL' : ''} ${MYSQLCHARSET} ${hasDef ? `DEFAULT '${field.def}'` : ''}`;
|
|
2152
2122
|
field[DBType.SqliteRemote] = field[DBType.Sqlite] = () => `${field.C2()} text`;
|
|
2123
|
+
field.Data2SQL = (data: any) => typeof data === 'string' ? new Date(data) : data;
|
|
2153
2124
|
break;
|
|
2154
2125
|
}
|
|
2155
2126
|
case SqlType.timestamp: {
|
|
2156
2127
|
field[DBType.Mysql] = () => `${field.C2()} timestamp ${config.notNull === true ? 'NOT NULL' : ''} ${MYSQLCHARSET} ${hasDef ? `DEFAULT '${field.def}'` : ''}`;
|
|
2157
2128
|
field[DBType.SqliteRemote] = field[DBType.Sqlite] = () => `${field.C2()} integer`;
|
|
2129
|
+
field.Data2SQL = (data: any) => typeof data === 'string' ? +new Date(data) : data;
|
|
2158
2130
|
break;
|
|
2159
2131
|
}
|
|
2160
2132
|
case SqlType.char: {
|
|
@@ -2269,6 +2241,7 @@ export const Field = (config: FieldOption) => {
|
|
|
2269
2241
|
let __columns = Reflect.getMetadata(_columns, object);
|
|
2270
2242
|
let __columnsNoId = Reflect.getMetadata(_columnsNoId, object);
|
|
2271
2243
|
let __ids = Reflect.getMetadata(_ids, object);
|
|
2244
|
+
let __logicIds = Reflect.getMetadata(_logicIds, object);
|
|
2272
2245
|
let __index = Reflect.getMetadata(_index, object);
|
|
2273
2246
|
let __def = Reflect.getMetadata(_def, object);
|
|
2274
2247
|
|
|
@@ -2287,16 +2260,23 @@ export const Field = (config: FieldOption) => {
|
|
|
2287
2260
|
} else {
|
|
2288
2261
|
__columnsNoId.push(propertyName);
|
|
2289
2262
|
}
|
|
2263
|
+
if (field.logicId === true) {
|
|
2264
|
+
__logicIds.push(propertyName);
|
|
2265
|
+
}
|
|
2290
2266
|
if (field.index === true) {
|
|
2291
2267
|
__index.push(propertyName);
|
|
2292
2268
|
}
|
|
2293
2269
|
if (hasDef) {
|
|
2294
2270
|
__def[propertyName] = field.def;
|
|
2295
2271
|
}
|
|
2272
|
+
if (field.comment) {
|
|
2273
|
+
__def[propertyName] = field.comment;
|
|
2274
|
+
}
|
|
2296
2275
|
Reflect.defineMetadata(_fields, __fields, object);
|
|
2297
2276
|
Reflect.defineMetadata(_columns, __columns, object);
|
|
2298
2277
|
Reflect.defineMetadata(_columnsNoId, __columnsNoId, object);
|
|
2299
2278
|
Reflect.defineMetadata(_ids, __ids, object);
|
|
2279
|
+
Reflect.defineMetadata(_logicIds, __logicIds, object);
|
|
2300
2280
|
Reflect.defineMetadata(_index, __index, object);
|
|
2301
2281
|
Reflect.defineMetadata(_def, __def, object);
|
|
2302
2282
|
if (field.hasOwnProperty('logicDelete')) {
|
|
@@ -2305,16 +2285,24 @@ export const Field = (config: FieldOption) => {
|
|
|
2305
2285
|
}
|
|
2306
2286
|
};
|
|
2307
2287
|
}
|
|
2288
|
+
const formatDialects = {
|
|
2289
|
+
[DBType.Mysql]: mysql,
|
|
2290
|
+
[DBType.Sqlite]: sqlite,
|
|
2291
|
+
[DBType.SqliteRemote]: sqlite
|
|
2292
|
+
};
|
|
2308
2293
|
export const DB = (config: ServiceOption) => {
|
|
2309
2294
|
return function <C extends { new(...args: any[]): {} }>(constructor: C) {
|
|
2310
2295
|
const __ids = Reflect.getMetadata(_ids, config.clz.prototype) || new Array<string>;
|
|
2296
|
+
const __logicIds = Reflect.getMetadata(_logicIds, config.clz.prototype) || new Array<string>;
|
|
2311
2297
|
const __fields = Reflect.getMetadata(_fields, config.clz.prototype);
|
|
2312
2298
|
const __columns = Reflect.getMetadata(_columns, config.clz.prototype);
|
|
2313
|
-
const __columnsNoId =
|
|
2299
|
+
const __columnsNoId = Reflect.getMetadata(_columnsNoId, config.clz.prototype);
|
|
2314
2300
|
const __stateFileName = Reflect.getMetadata(_stateFileName, config.clz.prototype);
|
|
2315
2301
|
const __deleteState = Reflect.getMetadata(_deleteState, config.clz.prototype);
|
|
2316
2302
|
const __index = Reflect.getMetadata(_index, config.clz.prototype);
|
|
2317
2303
|
const __def = Reflect.getMetadata(_def, config.clz.prototype);
|
|
2304
|
+
const __dbType = config.dbType ?? DBType.Mysql;
|
|
2305
|
+
const __formatDialect = formatDialects[__dbType];
|
|
2318
2306
|
const className = config.tableName?.replace(/_(\w)/g, (a: string, b: string) => b.toUpperCase());
|
|
2319
2307
|
const ClassName = className?.replace(/\w/, (v: string) => v.toUpperCase());
|
|
2320
2308
|
const vueName = config.tableName?.replace(/_/g, '-');
|
|
@@ -2323,17 +2311,21 @@ export const DB = (config: ServiceOption) => {
|
|
|
2323
2311
|
[_className] = className;
|
|
2324
2312
|
[_ClassName] = ClassName;
|
|
2325
2313
|
[_vueName] = vueName;
|
|
2314
|
+
|
|
2326
2315
|
[_daoDBName] = config.dbName;
|
|
2327
|
-
[_dbType] =
|
|
2316
|
+
[_dbType] = __dbType;
|
|
2317
|
+
[_formatDialect] = __formatDialect;
|
|
2328
2318
|
[_sqlite_version] = config.sqliteVersion;
|
|
2329
2319
|
[_SqlOption] = Object.assign({}, _defOption, config);
|
|
2330
2320
|
|
|
2331
2321
|
[_ids] = __ids;
|
|
2322
|
+
[_logicIds] = __logicIds;
|
|
2332
2323
|
[_fields] = __fields;
|
|
2333
2324
|
[_columns] = __columns;
|
|
2334
2325
|
[_columnsNoId] = __columnsNoId;
|
|
2335
2326
|
[_index] = __index;
|
|
2336
2327
|
[_def] = __def;
|
|
2328
|
+
[_comment] = config.comment;
|
|
2337
2329
|
[_stateFileName] = __stateFileName;
|
|
2338
2330
|
[_deleteState] = __deleteState;
|
|
2339
2331
|
|
|
@@ -2355,6 +2347,9 @@ export const DB = (config: ServiceOption) => {
|
|
|
2355
2347
|
.map(K => [K, FieldFilter(K as string, data[K as string], __def, __fields[K as string].uuid === true || __fields[K as string].uuidShort === true, option)])
|
|
2356
2348
|
.filter(data => {
|
|
2357
2349
|
if ((data[1] as any)[0] === 1) {
|
|
2350
|
+
if (__fields[data[0] as string].Data2SQL) {
|
|
2351
|
+
(data[1] as any)[1] = __fields[data[0] as string].Data2SQL((data[1] as any)[1]);
|
|
2352
|
+
}
|
|
2358
2353
|
if (option?.onFieldExists) {
|
|
2359
2354
|
option.onFieldExists(data[0] as string, (data[1] as any)[1]);
|
|
2360
2355
|
}
|
|
@@ -2418,7 +2413,9 @@ export class SqlService<T extends object> {
|
|
|
2418
2413
|
private [_ClassName]?: string;
|
|
2419
2414
|
private [_vueName]?: string;
|
|
2420
2415
|
private [_daoDBName]?: string;
|
|
2416
|
+
private [_comment]?: string;
|
|
2421
2417
|
private [_ids]?: string[];
|
|
2418
|
+
// private [_logicIds]?: string[];
|
|
2422
2419
|
private [_fields]?: Record<string, AField>;
|
|
2423
2420
|
private [_columns]?: string[];
|
|
2424
2421
|
private [_columnsNoId]?: string[];
|
|
@@ -2426,6 +2423,7 @@ export class SqlService<T extends object> {
|
|
|
2426
2423
|
private [_deleteState]?: string;
|
|
2427
2424
|
private [_SqlOption]?: ServiceOption;
|
|
2428
2425
|
private [_dbType]?: DBType;
|
|
2426
|
+
private [_formatDialect]?: DialectOptions;
|
|
2429
2427
|
private [_sqlite_version]?: string;
|
|
2430
2428
|
private [_index]?: string[];
|
|
2431
2429
|
private [_def]?: Partial<T>;
|
|
@@ -2445,6 +2443,7 @@ export class SqlService<T extends object> {
|
|
|
2445
2443
|
existConditionOtherThanIds?: (keyof T)[];
|
|
2446
2444
|
replaceWithDef?: boolean;
|
|
2447
2445
|
}): { sql: string; params?: any[] }[] {
|
|
2446
|
+
|
|
2448
2447
|
const sqls: { sql: string; params?: any[] }[] = [];
|
|
2449
2448
|
const tableName = Sqlstring.escapeId(option!.tableName);
|
|
2450
2449
|
switch (option?.mode) {
|
|
@@ -2493,10 +2492,10 @@ export class SqlService<T extends object> {
|
|
|
2493
2492
|
return `SELECT ${questMark.join(',')} FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM ${tableName} WHERE ${where})`;
|
|
2494
2493
|
});
|
|
2495
2494
|
const columnNames = iterare<string>(finalColumns).map(i => this[_fields]![i]?.C2()).join(',');
|
|
2496
|
-
const sql =
|
|
2495
|
+
const sql = formatDialect(`INSERT INTO
|
|
2497
2496
|
${tableName}
|
|
2498
2497
|
(${columnNames})
|
|
2499
|
-
${questMarks.join(' UNION ALL ')}
|
|
2498
|
+
${questMarks.join(' UNION ALL ')};`, { dialect: this[_formatDialect]! });
|
|
2500
2499
|
sqls.push({ sql, params });
|
|
2501
2500
|
break;
|
|
2502
2501
|
}
|
|
@@ -2531,12 +2530,12 @@ export class SqlService<T extends object> {
|
|
|
2531
2530
|
return `(${questMark.join(',')})`;
|
|
2532
2531
|
});
|
|
2533
2532
|
const columnNames = iterare(finalColumns).map(i => this[_fields]![i]?.C2()).join(',');
|
|
2534
|
-
const sql =
|
|
2533
|
+
const sql = formatDialect(`
|
|
2535
2534
|
${this[_dbType] === DBType.Mysql ? '' : 'INSERT OR'} REPLACE INTO
|
|
2536
2535
|
${tableName}
|
|
2537
2536
|
(${columnNames})
|
|
2538
2537
|
VALUES ${questMarks};
|
|
2539
|
-
|
|
2538
|
+
`, { dialect: this[_formatDialect]! });
|
|
2540
2539
|
sqls.push({ sql, params });
|
|
2541
2540
|
break;
|
|
2542
2541
|
}
|
|
@@ -2571,12 +2570,12 @@ export class SqlService<T extends object> {
|
|
|
2571
2570
|
return `(${questMark.join(',')})`;
|
|
2572
2571
|
});
|
|
2573
2572
|
const columnNames = iterare(finalColumns).map(i => this[_fields]![i]?.C2()).join(',');
|
|
2574
|
-
const sql =
|
|
2573
|
+
const sql = formatDialect(`
|
|
2575
2574
|
INSERT INTO
|
|
2576
2575
|
${tableName}
|
|
2577
2576
|
(${columnNames})
|
|
2578
2577
|
VALUES ${questMarks};
|
|
2579
|
-
|
|
2578
|
+
`, { dialect: this[_formatDialect]! });
|
|
2580
2579
|
|
|
2581
2580
|
sqls.push({ sql, params });
|
|
2582
2581
|
break;
|
|
@@ -2618,16 +2617,16 @@ export class SqlService<T extends object> {
|
|
|
2618
2617
|
sqls.push(..._sqls);
|
|
2619
2618
|
const columnNames = iterare(finalColumns).map(i => this[_fields]![i]?.C2()).join(',');
|
|
2620
2619
|
sqls.push({
|
|
2621
|
-
sql:
|
|
2620
|
+
sql: formatDialect(`
|
|
2622
2621
|
INSERT INTO
|
|
2623
2622
|
${tableTemp}
|
|
2624
2623
|
(${columnNames})
|
|
2625
2624
|
VALUES ${questMarks};
|
|
2626
|
-
|
|
2625
|
+
`, { dialect: this[_formatDialect]! }), params
|
|
2627
2626
|
});
|
|
2628
2627
|
sqls.push({
|
|
2629
|
-
sql:
|
|
2630
|
-
SELECT ${columnNames} FROM ${tableTemp}
|
|
2628
|
+
sql: formatDialect(`INSERT INTO ${Sqlstring.escapeId(option.tableName)} (${columnNames})
|
|
2629
|
+
SELECT ${columnNames} FROM ${tableTemp};`, { dialect: this[_formatDialect]! })
|
|
2631
2630
|
});
|
|
2632
2631
|
sqls.push({ sql: `DROP TABLE IF EXISTS ${tableTempESC};` });
|
|
2633
2632
|
break;
|
|
@@ -2698,23 +2697,21 @@ export class SqlService<T extends object> {
|
|
|
2698
2697
|
}
|
|
2699
2698
|
} else if (isArray) {
|
|
2700
2699
|
const fn = async () => {
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
return result;
|
|
2717
|
-
}, option?.conn);
|
|
2700
|
+
const result = await excuteSplit<Partial<T>, bigint>(
|
|
2701
|
+
ExcuteSplitMode.AsyncTrust,
|
|
2702
|
+
datas,
|
|
2703
|
+
async _data => {
|
|
2704
|
+
const sqls = this._insert(_data, option);
|
|
2705
|
+
let result = 0n;
|
|
2706
|
+
for (const { sql, params } of sqls) {
|
|
2707
|
+
const dd = await option!.conn!.execute(SyncMode.Async, sql, params);
|
|
2708
|
+
if (dd.insertId) { result += dd.insertId; }
|
|
2709
|
+
}
|
|
2710
|
+
return result;
|
|
2711
|
+
},
|
|
2712
|
+
{ everyLength: option?.every === true ? 1 : option?.maxDeal }
|
|
2713
|
+
);
|
|
2714
|
+
return result;
|
|
2718
2715
|
};
|
|
2719
2716
|
return new Promise<bigint[]>(async (resolve, reject) => {
|
|
2720
2717
|
try {
|
|
@@ -2787,13 +2784,13 @@ export class SqlService<T extends object> {
|
|
|
2787
2784
|
}
|
|
2788
2785
|
);
|
|
2789
2786
|
}
|
|
2790
|
-
const sql =
|
|
2787
|
+
const sql = formatDialect(`UPDATE ${tableName} SET ${iterare(this[_columnsNoId]!)
|
|
2791
2788
|
.filter(K => columnMaps[K]!.where.length > 0)
|
|
2792
2789
|
.map(K => {
|
|
2793
2790
|
params.push(...columnMaps[K]!.params);
|
|
2794
2791
|
return `${this[_fields]![K]?.C2()} = CASE ${columnMaps[K]!.where.join(' ')} ELSE ${this[_fields]![K]?.C2()} END`
|
|
2795
2792
|
})
|
|
2796
|
-
.join(',')}
|
|
2793
|
+
.join(',')};`, { dialect: this[_formatDialect]! });
|
|
2797
2794
|
sqls.push({ sql, params });
|
|
2798
2795
|
return sqls;
|
|
2799
2796
|
}
|
|
@@ -2939,13 +2936,13 @@ export class SqlService<T extends object> {
|
|
|
2939
2936
|
if (this[_stateFileName] !== undefined && option.forceDelete !== true) {
|
|
2940
2937
|
params.unshift(this[_deleteState]);
|
|
2941
2938
|
sqls.push({
|
|
2942
|
-
sql:
|
|
2939
|
+
sql: formatDialect(`
|
|
2943
2940
|
UPDATE ${tableNameESC} SET ${this[_fields]![this[_stateFileName]]?.C2()} = ?
|
|
2944
2941
|
WHERE ${whereSql};
|
|
2945
|
-
|
|
2942
|
+
`, { dialect: this[_formatDialect]! }), params
|
|
2946
2943
|
});
|
|
2947
2944
|
} else {
|
|
2948
|
-
sqls.push({ sql:
|
|
2945
|
+
sqls.push({ sql: formatDialect(`DELETE FROM ${tableNameESC} WHERE ${whereSql};`, { dialect: this[_formatDialect]! }), params });
|
|
2949
2946
|
}
|
|
2950
2947
|
} else {
|
|
2951
2948
|
sqls.push({ sql: `DROP TABLE IF EXISTS ${tableTempESC};` });
|
|
@@ -2956,13 +2953,13 @@ export class SqlService<T extends object> {
|
|
|
2956
2953
|
case DBType.Mysql: {
|
|
2957
2954
|
if (this[_stateFileName] !== undefined && option.forceDelete !== true) {
|
|
2958
2955
|
sqls.push({
|
|
2959
|
-
sql:
|
|
2960
|
-
SET a.${this[_fields]![this[_stateFileName]]?.C2()} =
|
|
2956
|
+
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 ')}
|
|
2957
|
+
SET a.${this[_fields]![this[_stateFileName]]?.C2()} = ?;`, { dialect: this[_formatDialect]! }),
|
|
2961
2958
|
params: [this[_deleteState]]
|
|
2962
2959
|
});
|
|
2963
2960
|
} else {
|
|
2964
2961
|
sqls.push({
|
|
2965
|
-
sql:
|
|
2962
|
+
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: this[_formatDialect]! })
|
|
2966
2963
|
});
|
|
2967
2964
|
}
|
|
2968
2965
|
break;
|
|
@@ -2972,12 +2969,12 @@ export class SqlService<T extends object> {
|
|
|
2972
2969
|
const columnNames = iterare(delWhere).map(K => this[_fields]![K]?.C2()).join(',');
|
|
2973
2970
|
if (this[_stateFileName] !== undefined && option.forceDelete !== true) {
|
|
2974
2971
|
sqls.push({
|
|
2975
|
-
sql:
|
|
2976
|
-
WHERE (${columnNames}) IN (SELECT ${columnNames} FROM ${tableTempESC})
|
|
2972
|
+
sql: formatDialect(`UPDATE ${tableNameESC} SET ${this[_fields]![this[_stateFileName]]?.C2()} = ?
|
|
2973
|
+
WHERE (${columnNames}) IN (SELECT ${columnNames} FROM ${tableTempESC});`, { dialect: this[_formatDialect]! }),
|
|
2977
2974
|
params: [this[_deleteState]]
|
|
2978
2975
|
});
|
|
2979
2976
|
} else {
|
|
2980
|
-
sqls.push({ sql:
|
|
2977
|
+
sqls.push({ sql: formatDialect(`DELETE FROM ${tableNameESC} WHERE (${columnNames}) IN (SELECT ${columnNames} FROM ${tableTempESC});`, { dialect: this[_formatDialect]! }) });
|
|
2981
2978
|
}
|
|
2982
2979
|
break;
|
|
2983
2980
|
}
|
|
@@ -3029,8 +3026,7 @@ export class SqlService<T extends object> {
|
|
|
3029
3026
|
return result[0] as T;
|
|
3030
3027
|
}
|
|
3031
3028
|
case TemplateResult.NotSureOne: {
|
|
3032
|
-
|
|
3033
|
-
return (result[0] as T) ?? null;
|
|
3029
|
+
return result && result.length > 0 ? (result[0] as T) ?? null : null;
|
|
3034
3030
|
}
|
|
3035
3031
|
case TemplateResult.Many: {
|
|
3036
3032
|
return result;
|
|
@@ -3102,13 +3098,13 @@ export class SqlService<T extends object> {
|
|
|
3102
3098
|
let resultIndex = -1;
|
|
3103
3099
|
if (option.mode === SelectMode.Common) {
|
|
3104
3100
|
const params = new Array<any>();
|
|
3105
|
-
const whereSql =
|
|
3101
|
+
const whereSql = formatDialect(iterare(wheres).map(where => this[_transformer]!(where, option)).map(where => {
|
|
3106
3102
|
return `SELECT ${columns} FROM ${tableNameESC} a WHERE
|
|
3107
3103
|
${Object.entries(where).map(([K, V]) => {
|
|
3108
3104
|
params.push(V);
|
|
3109
3105
|
return `${this[_fields]![K]?.C2()} = ?`;
|
|
3110
3106
|
}).join(' AND ')}`;
|
|
3111
|
-
}).join(' UNION ALL '));
|
|
3107
|
+
}).join(' UNION ALL '), { dialect: this[_formatDialect]! });
|
|
3112
3108
|
sqls.push({ sql: whereSql, params });
|
|
3113
3109
|
resultIndex = 0;
|
|
3114
3110
|
} else {
|
|
@@ -3117,7 +3113,7 @@ export class SqlService<T extends object> {
|
|
|
3117
3113
|
const _sqls = this._createTable<L>({ tableName: tableTemp, temp: true, columns: delWhere, data: wheres, index: 'all', id: 'none' })!;
|
|
3118
3114
|
sqls.push(..._sqls);
|
|
3119
3115
|
resultIndex = sqls.length;
|
|
3120
|
-
sqls.push({ sql:
|
|
3116
|
+
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: this[_formatDialect]! }) });
|
|
3121
3117
|
sqls.push({ sql: `DROP TABLE IF EXISTS ${tableTempESC};` });
|
|
3122
3118
|
}
|
|
3123
3119
|
|
|
@@ -3270,7 +3266,7 @@ export class SqlService<T extends object> {
|
|
|
3270
3266
|
const _params = Object.assign({}, option.context, option.params);
|
|
3271
3267
|
option.sql ??= globalThis[_sqlCache].load(this._matchSqlid(option.sqlId), { ctx: option.context, isCount: option.isCount, ..._params });
|
|
3272
3268
|
const params: any[] = [];
|
|
3273
|
-
const sql = option.sql?.replace(/\:([A-Za-z0-9._]+)/g, (txt, key) => {
|
|
3269
|
+
const sql = formatDialect(option.sql?.replace(/\:([A-Za-z0-9._]+)/g, (txt, key) => {
|
|
3274
3270
|
let V = LGet(_params, key);
|
|
3275
3271
|
if (V) {
|
|
3276
3272
|
if (V !== undefined) {
|
|
@@ -3295,7 +3291,7 @@ export class SqlService<T extends object> {
|
|
|
3295
3291
|
return '?';
|
|
3296
3292
|
}
|
|
3297
3293
|
return txt;
|
|
3298
|
-
});
|
|
3294
|
+
})!, { dialect: this[_formatDialect]! });
|
|
3299
3295
|
if (option.sync === SyncMode.Sync) {
|
|
3300
3296
|
const result = option!.conn!.query(SyncMode.Sync, sql, params);
|
|
3301
3297
|
return this._select<L>(option.selectResult, result, option.defValue, option.errorMsg, option.hump, option.mapper, option.mapperIfUndefined);
|
|
@@ -3334,7 +3330,7 @@ export class SqlService<T extends object> {
|
|
|
3334
3330
|
const _params = Object.assign({}, option.context, option.params);
|
|
3335
3331
|
option.sql ??= globalThis[_sqlCache].load(this._matchSqlid(option.sqlId), { ctx: option.context, ..._params });
|
|
3336
3332
|
const params: any[] = [];
|
|
3337
|
-
const sql = option.sql?.replace(/\:(\w+)/g, (txt, key) => {
|
|
3333
|
+
const sql = formatDialect(option.sql?.replace(/\:(\w+)/g, (txt, key) => {
|
|
3338
3334
|
let V = LGet(_params, key);
|
|
3339
3335
|
if (V) {
|
|
3340
3336
|
if (V !== undefined) {
|
|
@@ -3359,7 +3355,7 @@ export class SqlService<T extends object> {
|
|
|
3359
3355
|
return '?';
|
|
3360
3356
|
}
|
|
3361
3357
|
return txt;
|
|
3362
|
-
});
|
|
3358
|
+
})!, { dialect: this[_formatDialect]! });
|
|
3363
3359
|
if (option.sync === SyncMode.Sync) {
|
|
3364
3360
|
const result = option!.conn!.execute(SyncMode.Sync, sql, params);
|
|
3365
3361
|
return result.affectedRows;
|
|
@@ -3414,17 +3410,18 @@ export class SqlService<T extends object> {
|
|
|
3414
3410
|
return new StreamQuery<L>(option?.tableName ?? this[_tableName]!, this as any, this[_fields]!, this[_columns]!);
|
|
3415
3411
|
}
|
|
3416
3412
|
|
|
3417
|
-
|
|
3418
|
-
page<L = T>(option: MethodOption & { sync
|
|
3419
|
-
page<L = T>(option: MethodOption & { sync: SyncMode.Sync; sqlId: string; context?: any; params: Record<string, any>; pageSize: number; pageNumber: number; limitSelf?: boolean; countSelf?: boolean; sumSelf?: boolean; orderBy?: string; hump?: boolean; mapper?: string | SqlMapper; mapperIfUndefined?: MapperIfUndefined; }): PageQuery<L>;
|
|
3413
|
+
page<L = T>(option: MethodOption & { sync?: SyncMode.Async; sqlId: string; context?: any; params: Record<string, any>; pageSize?: number; pageNumber?: number; limitSelf?: boolean; countSelf?: boolean; sumSelf?: boolean; orderBy?: string; hump?: boolean; mapper?: string | SqlMapper; mapperIfUndefined?: MapperIfUndefined; }): Promise<PageQuery<L>>;
|
|
3414
|
+
page<L = T>(option: MethodOption & { sync: SyncMode.Sync; sqlId: string; context?: any; params: Record<string, any>; pageSize?: number; pageNumber?: number; limitSelf?: boolean; countSelf?: boolean; sumSelf?: boolean; orderBy?: string; hump?: boolean; mapper?: string | SqlMapper; mapperIfUndefined?: MapperIfUndefined; }): PageQuery<L>;
|
|
3420
3415
|
@P<T>()
|
|
3421
|
-
page<L = T>(option: MethodOption & { sync?: SyncMode; sqlId: string; context?: any; params: Record<string, any>; pageSize
|
|
3416
|
+
page<L = T>(option: MethodOption & { sync?: SyncMode; sqlId: string; context?: any; params: Record<string, any>; pageSize?: number; pageNumber?: number; limitSelf?: boolean; countSelf?: boolean; sumSelf?: boolean; orderBy?: string; hump?: boolean; mapper?: string | SqlMapper; mapperIfUndefined?: MapperIfUndefined; }): PageQuery<L> | Promise<PageQuery<L>> {
|
|
3422
3417
|
const result: PageQuery<L> = {
|
|
3423
3418
|
sum: {},
|
|
3424
3419
|
records: [],
|
|
3425
3420
|
size: 0,
|
|
3426
3421
|
total: 0
|
|
3427
3422
|
};
|
|
3423
|
+
option.pageNumber ??= 1;
|
|
3424
|
+
option.pageSize ??= 0;
|
|
3428
3425
|
Object.assign(option.params, {
|
|
3429
3426
|
limitStart: calc(option.pageNumber).sub(1).mul(option.pageSize).over(),
|
|
3430
3427
|
limitEnd: calc(option.pageSize).over(),
|
|
@@ -3495,7 +3492,7 @@ export class SqlService<T extends object> {
|
|
|
3495
3492
|
selectResult: SelectResult.R_C_Assert
|
|
3496
3493
|
});
|
|
3497
3494
|
result.size = calc(result.total)
|
|
3498
|
-
.add(option.pageSize - 1)
|
|
3495
|
+
.add(option.pageSize ?? 10 - 1)
|
|
3499
3496
|
.div(option.pageSize)
|
|
3500
3497
|
.round(0, 2)
|
|
3501
3498
|
.over();
|
|
@@ -3524,6 +3521,177 @@ export class SqlService<T extends object> {
|
|
|
3524
3521
|
}
|
|
3525
3522
|
}
|
|
3526
3523
|
|
|
3524
|
+
/**
|
|
3525
|
+
* 导出数据,可以为EJS-EXCEL直接使用
|
|
3526
|
+
* @param list
|
|
3527
|
+
* @returns
|
|
3528
|
+
*/
|
|
3529
|
+
exp<L = T>(list: L[]) {
|
|
3530
|
+
Throw.if(list.length === 0, 'not found data!');
|
|
3531
|
+
const columnTitles = new Array<string>();
|
|
3532
|
+
const keys = this[_fields] ?
|
|
3533
|
+
iterare(Object.entries(this[_fields]))
|
|
3534
|
+
.filter(([K, F]) => (F.id !== true && F.exportable !== false) || (F.id === true && F.exportable === true))
|
|
3535
|
+
.map(([K, F]) => {
|
|
3536
|
+
columnTitles.push(F.comment ?? K);
|
|
3537
|
+
return K;
|
|
3538
|
+
}).toArray()
|
|
3539
|
+
: Object.keys(list[0]!).filter(K => !this[_ids]?.includes(K));
|
|
3540
|
+
const title = this[_comment] ?? this[_tableName];
|
|
3541
|
+
const titleSpan = `A1:${ten2Any(keys.length)}1`;
|
|
3542
|
+
const datas = list.map(data => keys.map(k => data[k] ?? ''));
|
|
3543
|
+
return { title, titleSpan, columnTitles, datas };
|
|
3544
|
+
}
|
|
3545
|
+
/**
|
|
3546
|
+
* 导入数据的模板
|
|
3547
|
+
* @returns
|
|
3548
|
+
*/
|
|
3549
|
+
imp() {
|
|
3550
|
+
Throw.if(!this[_fields], 'not set fields!');
|
|
3551
|
+
const columnTitles = new Array<string>();
|
|
3552
|
+
const keys = iterare(Object.entries(this[_fields]!))
|
|
3553
|
+
.filter(([K, F]) => (F.id !== true && F.exportable !== false) || (F.id === true && F.exportable === true))
|
|
3554
|
+
.map(([K, F]) => {
|
|
3555
|
+
columnTitles.push(F.comment ?? K);
|
|
3556
|
+
return K;
|
|
3557
|
+
}).toArray();
|
|
3558
|
+
const title = this[_comment] ?? this[_tableName];
|
|
3559
|
+
const titleSpan = `A1:${ten2Any(keys.length)}1`;
|
|
3560
|
+
return { title, titleSpan, columnTitles };
|
|
3561
|
+
}
|
|
3562
|
+
|
|
3563
|
+
/**
|
|
3564
|
+
* 初始化表结构
|
|
3565
|
+
* 只有sqlite、sqliteremote需要
|
|
3566
|
+
* force: 是否强制,默认false, 强制时会删除再创建
|
|
3567
|
+
* @param option
|
|
3568
|
+
*/
|
|
3569
|
+
init(option?: MethodOption & { sync?: SyncMode.Async; force?: boolean }): Promise<void>;
|
|
3570
|
+
init(option: MethodOption & { sync: SyncMode.Sync; force?: boolean }): void;
|
|
3571
|
+
@P<T>()
|
|
3572
|
+
init(option?: MethodOption & { sync?: SyncMode; force?: boolean }): void | Promise<void> {
|
|
3573
|
+
const tableES = Sqlstring.escapeId(option!.tableName);
|
|
3574
|
+
option!.force ??= false;
|
|
3575
|
+
if (this[_dbType] === DBType.Sqlite) {
|
|
3576
|
+
if (option?.force) {
|
|
3577
|
+
option!.conn!.execute(SyncMode.Sync, `DROP TABLE IF EXISTS ${tableES};`);
|
|
3578
|
+
}
|
|
3579
|
+
const lastVersion = this[_sqlite_version] ?? '0.0.1';
|
|
3580
|
+
// 检查表
|
|
3581
|
+
const tableCheckResult = option!.conn!.pluck<number>(SyncMode.Sync, `SELECT COUNT(1) t FROM sqlite_master WHERE TYPE = 'table' AND name = ?`, [option!.tableName]);
|
|
3582
|
+
if (tableCheckResult) {
|
|
3583
|
+
// 旧版本
|
|
3584
|
+
const tableVersion = option!.conn!.pluck<string>(SyncMode.Sync, 'SELECT ______version v from TABLE_VERSION WHERE ______tableName = ?', [option!.tableName]);
|
|
3585
|
+
if (tableVersion && tableVersion < lastVersion) { // 发现需要升级的版本
|
|
3586
|
+
// 更新版本
|
|
3587
|
+
const columns = iterare<{ name: string }>(option!.conn!.query(SyncMode.Sync, `PRAGMA table_info(${tableES})`))
|
|
3588
|
+
.filter(c => this[_fields]!.hasOwnProperty(C2P(c.name, globalThis[_Hump])))
|
|
3589
|
+
.map(c => Sqlstring.escapeId(c.name))
|
|
3590
|
+
.join(',');
|
|
3591
|
+
|
|
3592
|
+
const rtable = Sqlstring.escapeId(`${option!.tableName}_${tableVersion.replace(/\./, '_')}`);
|
|
3593
|
+
option!.conn!.execute(SyncMode.Sync, `DROP TABLE IF EXISTS ${rtable};`);
|
|
3594
|
+
option!.conn!.execute(SyncMode.Sync, `ALTER TABLE ${tableES} RENAME TO ${rtable};`);
|
|
3595
|
+
option!.conn!.execute(SyncMode.Sync, `
|
|
3596
|
+
CREATE TABLE IF NOT EXISTS ${tableES}(
|
|
3597
|
+
${Object.values(this[_fields]!).map(K => K[DBType.Sqlite]()).join(',')}
|
|
3598
|
+
${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields]![i]?.C2()).join(',')})` : ''}
|
|
3599
|
+
);
|
|
3600
|
+
`);
|
|
3601
|
+
if (this[_index] && this[_index].length) {
|
|
3602
|
+
for (const index of this[_index]) {
|
|
3603
|
+
option!.conn!.execute(SyncMode.Sync, `CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${tableES} ("${this[_fields]![index]?.C2()}");`);
|
|
3604
|
+
}
|
|
3605
|
+
}
|
|
3606
|
+
option!.conn!.execute(SyncMode.Sync, `INSERT INTO ${tableES} (${columns}) SELECT ${columns} FROM ${rtable};`);
|
|
3607
|
+
option!.conn!.execute(SyncMode.Sync, `INSERT INTO ${tableES} (${columns}) SELECT ${columns} FROM ${rtable};`);
|
|
3608
|
+
option!.conn!.execute(SyncMode.Sync, `DROP TABLE IF EXISTS ${rtable};`);
|
|
3609
|
+
// 更新完毕,保存版本号
|
|
3610
|
+
option!.conn!.execute(SyncMode.Sync, 'UPDATE TABLE_VERSION SET ______version = ? WHERE ______tableName = ?', [option!.tableName, lastVersion]);
|
|
3611
|
+
} else if (!tableVersion) { // 不需要升级情况:没有旧的版本号
|
|
3612
|
+
option!.conn!.execute(SyncMode.Sync, 'INSERT INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option!.tableName, lastVersion]);
|
|
3613
|
+
}
|
|
3614
|
+
} else { // 表不存在
|
|
3615
|
+
// 创建表
|
|
3616
|
+
option!.conn!.execute(SyncMode.Sync, `
|
|
3617
|
+
CREATE TABLE IF NOT EXISTS ${tableES} (
|
|
3618
|
+
${Object.values(this[_fields]!).map(K => K[DBType.Sqlite]()).join(',')}
|
|
3619
|
+
${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields]![i]?.C2()).join(',')})` : ''}
|
|
3620
|
+
|
|
3621
|
+
);
|
|
3622
|
+
`);
|
|
3623
|
+
if (this[_index] && this[_index].length) {
|
|
3624
|
+
for (const index of this[_index]) {
|
|
3625
|
+
option!.conn!.execute(SyncMode.Sync, `CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${tableES} ("${this[_fields]![index]?.C2()}");`);
|
|
3626
|
+
}
|
|
3627
|
+
}
|
|
3628
|
+
option!.conn!.execute(SyncMode.Sync, 'INSERT OR REPLACE INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option!.tableName, lastVersion]);
|
|
3629
|
+
}
|
|
3630
|
+
} else if (this[_dbType] === DBType.SqliteRemote) {
|
|
3631
|
+
|
|
3632
|
+
return new Promise(async (resolve, reject) => {
|
|
3633
|
+
try {
|
|
3634
|
+
if (option?.force) {
|
|
3635
|
+
await option!.conn!.execute(SyncMode.Async, `DROP TABLE IF EXISTS ${tableES};`);
|
|
3636
|
+
}
|
|
3637
|
+
const lastVersion = this[_sqlite_version] ?? '0.0.1';
|
|
3638
|
+
// 检查表
|
|
3639
|
+
const tableCheckResult = await option!.conn!.pluck<number>(SyncMode.Async, `SELECT COUNT(1) t FROM sqlite_master WHERE TYPE = 'table' AND name = ?`, [option!.tableName]);
|
|
3640
|
+
if (tableCheckResult) {
|
|
3641
|
+
// 旧版本
|
|
3642
|
+
const tableVersion = await option!.conn!.pluck<string>(SyncMode.Async, 'SELECT ______version v from TABLE_VERSION WHERE ______tableName = ?', [option!.tableName]);
|
|
3643
|
+
if (tableVersion && tableVersion < lastVersion) { // 发现需要升级的版本
|
|
3644
|
+
// 更新版本
|
|
3645
|
+
const columns = iterare<{ name: string }>(await option!.conn!.query(SyncMode.Async, `PRAGMA table_info(${tableES})`))
|
|
3646
|
+
.filter(c => this[_fields]!.hasOwnProperty(C2P(c.name, globalThis[_Hump])))
|
|
3647
|
+
.map(c => Sqlstring.escapeId(c.name))
|
|
3648
|
+
.join(',');
|
|
3649
|
+
|
|
3650
|
+
const rtable = `${option!.tableName}_${tableVersion.replace(/\./, '_')}`;
|
|
3651
|
+
await option!.conn!.execute(SyncMode.Async, `DROP TABLE IF EXISTS ${rtable};`);
|
|
3652
|
+
await option!.conn!.execute(SyncMode.Async, `ALTER TABLE ${tableES} RENAME TO ${rtable};`);
|
|
3653
|
+
await option!.conn!.execute(SyncMode.Async, `
|
|
3654
|
+
CREATE TABLE IF NOT EXISTS ${tableES}(
|
|
3655
|
+
${Object.values(this[_fields]!).map(K => K[DBType.Sqlite]()).join(',')}
|
|
3656
|
+
${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields]![i]?.C2()).join(',')})` : ''}
|
|
3657
|
+
);
|
|
3658
|
+
`);
|
|
3659
|
+
if (this[_index] && this[_index].length) {
|
|
3660
|
+
for (const index of this[_index]) {
|
|
3661
|
+
await option!.conn!.execute(SyncMode.Async, `CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${tableES} ("${this[_fields]![index]?.C2()}");`);
|
|
3662
|
+
}
|
|
3663
|
+
}
|
|
3664
|
+
await option!.conn!.execute(SyncMode.Async, `INSERT INTO ${tableES} (${columns}) SELECT ${columns} FROM ${rtable};`);
|
|
3665
|
+
await option!.conn!.execute(SyncMode.Async, `INSERT INTO ${tableES} (${columns}) SELECT ${columns} FROM ${rtable};`);
|
|
3666
|
+
await option!.conn!.execute(SyncMode.Async, `DROP TABLE IF EXISTS ${rtable};`);
|
|
3667
|
+
// 更新完毕,保存版本号
|
|
3668
|
+
await option!.conn!.execute(SyncMode.Async, 'UPDATE TABLE_VERSION SET ______version = ? WHERE ______tableName = ?', [option!.tableName, lastVersion]);
|
|
3669
|
+
} else if (!tableVersion) { // 不需要升级情况:没有旧的版本号
|
|
3670
|
+
await option!.conn!.execute(SyncMode.Async, 'INSERT INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option!.tableName, lastVersion]);
|
|
3671
|
+
}
|
|
3672
|
+
} else { // 表不存在
|
|
3673
|
+
// 创建表
|
|
3674
|
+
await option!.conn!.execute(SyncMode.Async, `
|
|
3675
|
+
CREATE TABLE IF NOT EXISTS ${tableES}(
|
|
3676
|
+
${Object.values(this[_fields]!).map(K => K[DBType.Sqlite]()).join(',')}
|
|
3677
|
+
${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields]![i]?.C2()).join(',')})` : ''}
|
|
3678
|
+
);
|
|
3679
|
+
`);
|
|
3680
|
+
if (this[_index] && this[_index].length) {
|
|
3681
|
+
for (const index of this[_index]) {
|
|
3682
|
+
await option!.conn!.execute(SyncMode.Async, `CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${Sqlstring.escapeId(option!.tableName)} ("${this[_fields]![index]?.C2()}");`);
|
|
3683
|
+
}
|
|
3684
|
+
}
|
|
3685
|
+
await option!.conn!.execute(SyncMode.Async, 'INSERT OR REPLACE INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option!.tableName, lastVersion]);
|
|
3686
|
+
}
|
|
3687
|
+
resolve();
|
|
3688
|
+
} catch (error) {
|
|
3689
|
+
reject(error);
|
|
3690
|
+
}
|
|
3691
|
+
});
|
|
3692
|
+
}
|
|
3693
|
+
}
|
|
3694
|
+
|
|
3527
3695
|
/**
|
|
3528
3696
|
#创建表
|
|
3529
3697
|
** `tableName` 表名称
|
|
@@ -3569,16 +3737,16 @@ export class SqlService<T extends object> {
|
|
|
3569
3737
|
tableName = Sqlstring.escapeId(tableName ?? this[_tableName]);
|
|
3570
3738
|
switch (this[_dbType]) {
|
|
3571
3739
|
case DBType.Mysql: {
|
|
3572
|
-
let sql =
|
|
3740
|
+
let sql = formatDialect(`CREATE ${temp === true ? 'TEMPORARY' : ''} TABLE IF NOT EXISTS ${tableName}(
|
|
3573
3741
|
${columns.map(K => this[_fields]![K]![DBType.Mysql]()).join(',')}
|
|
3574
3742
|
${ids && ids.length ? `,PRIMARY KEY (${ids.map(i => this[_fields]![i]?.C2()).join(',')}) USING BTREE ` : ''}
|
|
3575
3743
|
${indexs && indexs.length ? `,${indexs.map(i => `KEY ${this[_fields]![i]?.C2()} (${this[_fields]![i]?.C2()})`).join(',')} ` : ''}
|
|
3576
|
-
) ENGINE=MEMORY
|
|
3744
|
+
) ENGINE=MEMORY;`, { dialect: this[_formatDialect]! });
|
|
3577
3745
|
sqls.push({ sql });
|
|
3578
3746
|
if (data && data.length > 0) {
|
|
3579
3747
|
const params: any[] = [];
|
|
3580
3748
|
let first = true;
|
|
3581
|
-
sql =
|
|
3749
|
+
sql = formatDialect(`INSERT INTO ${tableName} (${columns.map(c => this[_fields]![c]?.C2()).join(',')})
|
|
3582
3750
|
${(data).map(d => {
|
|
3583
3751
|
const r = `SELECT ${Object.entries(d).map(([K, V]) => {
|
|
3584
3752
|
params.push(V);
|
|
@@ -3586,28 +3754,28 @@ export class SqlService<T extends object> {
|
|
|
3586
3754
|
}).join(',')}`;
|
|
3587
3755
|
first = false;
|
|
3588
3756
|
return r;
|
|
3589
|
-
}).join(' UNION ALL ')}
|
|
3757
|
+
}).join(' UNION ALL ')}`, { dialect: this[_formatDialect]! });
|
|
3590
3758
|
sqls.push({ sql, params });
|
|
3591
3759
|
}
|
|
3592
3760
|
break;
|
|
3593
3761
|
}
|
|
3594
3762
|
case DBType.Sqlite:
|
|
3595
3763
|
case DBType.SqliteRemote: {
|
|
3596
|
-
let sql =
|
|
3764
|
+
let sql = formatDialect(`CREATE ${temp === true ? 'TEMPORARY' : ''} TABLE IF NOT EXISTS ${tableName}(
|
|
3597
3765
|
${columns.map(K => this[_fields]![K]![DBType.Sqlite]()).join(',')}
|
|
3598
3766
|
${ids && ids.length ? `,PRIMARY KEY (${ids.map(i => this[_fields]![i]?.C2()).join(',')}) ` : ''}
|
|
3599
|
-
)
|
|
3767
|
+
);`, { dialect: this[_formatDialect]! });
|
|
3600
3768
|
sqls.push({ sql });
|
|
3601
3769
|
if (indexs) {
|
|
3602
3770
|
for (const index of indexs) {
|
|
3603
|
-
sql =
|
|
3771
|
+
sql = formatDialect(`CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${tableName} (${this[_fields]![index]?.C2()});`, { dialect: this[_formatDialect]! });
|
|
3604
3772
|
sqls.push({ sql });
|
|
3605
3773
|
}
|
|
3606
3774
|
}
|
|
3607
3775
|
if (data && data.length > 0) {
|
|
3608
3776
|
const params: any[] = [];
|
|
3609
3777
|
let first = true;
|
|
3610
|
-
sql =
|
|
3778
|
+
sql = formatDialect(`INSERT INTO ${tableName} (${columns.map(c => this[_fields]![c]?.C2()).join(',')})
|
|
3611
3779
|
${(data).map(d => {
|
|
3612
3780
|
const r = `SELECT ${Object.entries(d).map(([K, V]) => {
|
|
3613
3781
|
params.push(V);
|
|
@@ -3615,7 +3783,7 @@ export class SqlService<T extends object> {
|
|
|
3615
3783
|
}).join(',')}`;
|
|
3616
3784
|
first = false;
|
|
3617
3785
|
return r;
|
|
3618
|
-
}).join(' UNION ALL ')}
|
|
3786
|
+
}).join(' UNION ALL ')}`, { dialect: this[_formatDialect]! });
|
|
3619
3787
|
sqls.push({ sql, params });
|
|
3620
3788
|
}
|
|
3621
3789
|
break;
|
|
@@ -4100,7 +4268,10 @@ class StreamQuery<T extends object> {
|
|
|
4100
4268
|
}
|
|
4101
4269
|
}
|
|
4102
4270
|
if (sets.length > 0) {
|
|
4103
|
-
const sql = `UPDATE ${this._table} SET ${sets.join(',')}
|
|
4271
|
+
const sql = `UPDATE ${this._table} SET ${sets.join(',')}
|
|
4272
|
+
${where ? ' WHERE ' : ''}
|
|
4273
|
+
${where}
|
|
4274
|
+
`;
|
|
4104
4275
|
if (option.sync === SyncMode.Async) {
|
|
4105
4276
|
return this._service.excute({ sync: SyncMode.Async, sql, params });
|
|
4106
4277
|
} else {
|
|
@@ -4117,7 +4288,10 @@ class StreamQuery<T extends object> {
|
|
|
4117
4288
|
option ??= {};
|
|
4118
4289
|
option.sync ??= SyncMode.Async;
|
|
4119
4290
|
const { where, params } = this._where();
|
|
4120
|
-
const sql = `DELETE FROM ${this._table}
|
|
4291
|
+
const sql = `DELETE FROM ${this._table}
|
|
4292
|
+
${where ? ' WHERE ' : ''}
|
|
4293
|
+
${where}
|
|
4294
|
+
`;
|
|
4121
4295
|
if (option.sync === SyncMode.Async) {
|
|
4122
4296
|
return this._service.excute({ sync: SyncMode.Async, sql, params });
|
|
4123
4297
|
} else {
|