baja-lite 1.0.6 → 1.0.10
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 +7 -4
- 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 +89 -34
- package/cjs/sql.js +348 -223
- 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 +4 -4
- 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 +89 -34
- package/es/sql.js +349 -224
- package/es/sqlite.d.ts +5 -8
- package/es/sqlite.js +25 -22
- 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 +4 -6
- 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/object.ts +1 -1
- package/src/set-ex.ts +49 -58
- package/src/sql.ts +357 -214
- package/src/sqlite.ts +26 -20
- package/src/test-mysql.ts +30 -28
package/src/sql.ts
CHANGED
|
@@ -5,15 +5,17 @@ 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
|
-
|
|
16
|
+
import { EnumMap } from 'enum';
|
|
17
|
+
import { encode, decode } from "@msgpack/msgpack";
|
|
18
|
+
(BigInt.prototype as any).toJSON = function () { return this.toString() }
|
|
17
19
|
// #region 常量
|
|
18
20
|
const _daoDBName = Symbol('dbName');
|
|
19
21
|
const _tableName = Symbol('tableName');
|
|
@@ -21,6 +23,7 @@ const _className = Symbol('className');
|
|
|
21
23
|
const _ClassName = Symbol('ClassName');
|
|
22
24
|
const _vueName = Symbol('vueName');
|
|
23
25
|
const _ids = Symbol('ids');
|
|
26
|
+
const _logicIds = Symbol('logicIds');
|
|
24
27
|
const _columns = Symbol('columns');
|
|
25
28
|
const _columnsNoId = Symbol('columnsNoId');
|
|
26
29
|
const _fields = Symbol('fields');
|
|
@@ -29,10 +32,12 @@ const _deleteState = Symbol('deleteState');
|
|
|
29
32
|
const _transformer = Symbol('transformer');
|
|
30
33
|
const _index = Symbol('index');
|
|
31
34
|
const _def = Symbol('def');
|
|
35
|
+
const _comment = Symbol('comment');
|
|
32
36
|
export const _sqlCache = Symbol('sqlMap');
|
|
33
37
|
export const _dao = Symbol('dao');
|
|
34
38
|
export const _primaryDB = Symbol('primaryDB');
|
|
35
39
|
const _dbType = Symbol('dbType');
|
|
40
|
+
const _formatDialect = Symbol('FormatDialect');
|
|
36
41
|
const _sqlite_version = Symbol('sqlite_version');
|
|
37
42
|
const _daoConnection = Symbol('daoConnection');
|
|
38
43
|
const _inTransaction = Symbol('inTransaction');
|
|
@@ -41,6 +46,7 @@ const _sqliteRemoteName = Symbol('sqliteRemoteName');
|
|
|
41
46
|
const _SqlOption = Symbol('SqlOption');
|
|
42
47
|
const _resultMap = Symbol('resultMap');
|
|
43
48
|
const _resultMap_SQLID = Symbol('resultMap_SQLID');
|
|
49
|
+
export const _enums = Symbol('_enums');
|
|
44
50
|
export const _Hump = Symbol('Hump');
|
|
45
51
|
export const _GlobalSqlOption = Symbol('GlobalSqlOption');
|
|
46
52
|
export const _EventBus = Symbol('EventBus');
|
|
@@ -248,6 +254,8 @@ interface ServiceOption {
|
|
|
248
254
|
dbType?: DBType;
|
|
249
255
|
/** SQLite版本以及升级为该版本时需要执行的SQL,初始版本为0.0.1,切记每个位置不要变为两位数*/
|
|
250
256
|
sqliteVersion?: string;
|
|
257
|
+
/** 备注 */
|
|
258
|
+
comment?: string;
|
|
251
259
|
}
|
|
252
260
|
/**
|
|
253
261
|
# 全局行为配置文件
|
|
@@ -309,6 +317,23 @@ export interface GlobalSqlOptionForWeb {
|
|
|
309
317
|
]
|
|
310
318
|
*/
|
|
311
319
|
sqlMapperMap?: SqlMappers;
|
|
320
|
+
/** 提供的枚举MAP */
|
|
321
|
+
enums?: EnumMap;
|
|
322
|
+
/**
|
|
323
|
+
* `列名与属性映射` 是否自动将下划线转为驼峰,默认NONE,即不转.
|
|
324
|
+
* 当设置为columnMode.HUMP时,切记将代码生成器中属性名称改对
|
|
325
|
+
* # 自定义sql查询时,无法自动转换哦,可使用标签转换:
|
|
326
|
+
*```
|
|
327
|
+
SELECT
|
|
328
|
+
* {{#hump}} seller_sku2, seller_sku {{/hump}}
|
|
329
|
+
* ```
|
|
330
|
+
* 转换为
|
|
331
|
+
*```
|
|
332
|
+
SELECT
|
|
333
|
+
* {{#hump}} seller_sku2 sellerSku2, seller_sku sellerSku {{/hump}}
|
|
334
|
+
* ```
|
|
335
|
+
*/
|
|
336
|
+
columnMode?: ColumnMode;
|
|
312
337
|
}
|
|
313
338
|
/**
|
|
314
339
|
# 全局行为配置文件
|
|
@@ -370,12 +395,13 @@ export interface GlobalSqlOption extends GlobalSqlOptionForWeb {
|
|
|
370
395
|
export default {
|
|
371
396
|
'sql_1': 'SELECT * FROM user WHERE username = :username',
|
|
372
397
|
'sql_2': (options: {
|
|
373
|
-
ctx
|
|
398
|
+
ctx?: any;
|
|
374
399
|
isCount?: boolean;
|
|
400
|
+
isSum?: boolean;
|
|
375
401
|
limitStart?: number;
|
|
376
402
|
limitEnd?: number;
|
|
377
403
|
orderBy?: string;
|
|
378
|
-
|
|
404
|
+
params?: Record<string, any>;
|
|
379
405
|
}) => {
|
|
380
406
|
return `
|
|
381
407
|
SELECT * FROM user u LEFT JOIN organ o ON u.orgid = o.orgid
|
|
@@ -442,21 +468,7 @@ export interface GlobalSqlOption extends GlobalSqlOptionForWeb {
|
|
|
442
468
|
*/
|
|
443
469
|
Redis?: Record<string, Record<string, any>> | Record<string, any>;
|
|
444
470
|
|
|
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;
|
|
471
|
+
|
|
460
472
|
/**
|
|
461
473
|
* 读取查询语句时,是否扫描JS文件?
|
|
462
474
|
* JS文件需要默认导出一个 SqlModel对象
|
|
@@ -474,9 +486,16 @@ interface FieldOption extends Object {
|
|
|
474
486
|
index?: boolean;
|
|
475
487
|
id?: boolean;
|
|
476
488
|
logicDelete?: string | number;
|
|
489
|
+
/** 是否逻辑唯一,用于导入时检测数据是否存在 */
|
|
490
|
+
logicId?: boolean;
|
|
477
491
|
/** 仅在生成 表时有效 */
|
|
478
492
|
notNull?: boolean;
|
|
493
|
+
/** 注释,影响到默认导出导入标题 */
|
|
479
494
|
comment?: string;
|
|
495
|
+
/** 可以导入的字段,默认TRUE,ID默认FALSE */
|
|
496
|
+
importable?: boolean;
|
|
497
|
+
/** 可以导出的字段,默认TRUE,ID默认FALSE */
|
|
498
|
+
exportable?: boolean;
|
|
480
499
|
/** sqlite 无效,与UUID只能有一个 */
|
|
481
500
|
uuidShort?: boolean;
|
|
482
501
|
/** 与uuidShort只能有一个 */
|
|
@@ -493,6 +512,7 @@ interface AField extends FieldOption {
|
|
|
493
512
|
[DBType.Mysql]: () => string;
|
|
494
513
|
[DBType.Sqlite]: () => string;
|
|
495
514
|
[DBType.SqliteRemote]: () => string;
|
|
515
|
+
Data2SQL: (data: any) => any;
|
|
496
516
|
}
|
|
497
517
|
export interface PageQuery<L> {
|
|
498
518
|
sum?: Record<string, number>;
|
|
@@ -505,12 +525,11 @@ export interface PageQuery<L> {
|
|
|
505
525
|
// #region 数据方言
|
|
506
526
|
/** sqlite electron服务端需要支持的接口 */
|
|
507
527
|
export interface SqliteRemoteInterface {
|
|
508
|
-
execute(
|
|
509
|
-
pluck
|
|
510
|
-
get
|
|
511
|
-
raw
|
|
512
|
-
query
|
|
513
|
-
|
|
528
|
+
execute(inData: Uint8Array): | Promise<Uint8Array>
|
|
529
|
+
pluck(inData: Uint8Array): Promise<Uint8Array>;
|
|
530
|
+
get(inData: Uint8Array): Promise<Uint8Array>;
|
|
531
|
+
raw(inData: Uint8Array): Promise<Uint8Array>;
|
|
532
|
+
query(inData: Uint8Array): Promise<Uint8Array>;
|
|
514
533
|
initDB(dbName: string): Promise<void>;
|
|
515
534
|
export(dbName: string): Promise<void>;
|
|
516
535
|
restore(dbName: string, fromName: string): Promise<void>;
|
|
@@ -1059,7 +1078,8 @@ export class SqliteRemoteConnection implements Connection {
|
|
|
1059
1078
|
}
|
|
1060
1079
|
return new Promise<{ affectedRows: number; insertId: bigint; }>(async (resolve, reject) => {
|
|
1061
1080
|
try {
|
|
1062
|
-
const
|
|
1081
|
+
const data = await this[_daoConnection].execute(encode([this[_sqliteRemoteName], sql, params]));
|
|
1082
|
+
const { affectedRows, insertId } = decode(data) as { affectedRows: number; insertId: bigint; };
|
|
1063
1083
|
resolve({ affectedRows, insertId: insertId ? BigInt(insertId) : 0n });
|
|
1064
1084
|
} catch (error) {
|
|
1065
1085
|
logger.error(`
|
|
@@ -1086,7 +1106,8 @@ export class SqliteRemoteConnection implements Connection {
|
|
|
1086
1106
|
}
|
|
1087
1107
|
return new Promise<T | null>(async (resolve, reject) => {
|
|
1088
1108
|
try {
|
|
1089
|
-
const
|
|
1109
|
+
const data = await this[_daoConnection].pluck(encode([this[_sqliteRemoteName], sql, params]));
|
|
1110
|
+
const r = decode(data) as T;
|
|
1090
1111
|
resolve(r);
|
|
1091
1112
|
} catch (error) {
|
|
1092
1113
|
logger.error(`
|
|
@@ -1113,7 +1134,8 @@ export class SqliteRemoteConnection implements Connection {
|
|
|
1113
1134
|
}
|
|
1114
1135
|
return new Promise<T | null>(async (resolve, reject) => {
|
|
1115
1136
|
try {
|
|
1116
|
-
const
|
|
1137
|
+
const data = await this[_daoConnection].pluck(encode([this[_sqliteRemoteName], sql, params]));
|
|
1138
|
+
const r = decode(data) as T;
|
|
1117
1139
|
resolve(r);
|
|
1118
1140
|
} catch (error) {
|
|
1119
1141
|
logger.error(`
|
|
@@ -1140,7 +1162,8 @@ export class SqliteRemoteConnection implements Connection {
|
|
|
1140
1162
|
}
|
|
1141
1163
|
return new Promise<T[]>(async (resolve, reject) => {
|
|
1142
1164
|
try {
|
|
1143
|
-
const
|
|
1165
|
+
const data = await this[_daoConnection].pluck(encode([this[_sqliteRemoteName], sql, params]));
|
|
1166
|
+
const r = decode(data) as T[];
|
|
1144
1167
|
resolve(r);
|
|
1145
1168
|
} catch (error) {
|
|
1146
1169
|
logger.error(`
|
|
@@ -1167,7 +1190,8 @@ export class SqliteRemoteConnection implements Connection {
|
|
|
1167
1190
|
}
|
|
1168
1191
|
return new Promise<T[]>(async (resolve, reject) => {
|
|
1169
1192
|
try {
|
|
1170
|
-
const
|
|
1193
|
+
const data = await this[_daoConnection].pluck(encode([this[_sqliteRemoteName], sql, params]));
|
|
1194
|
+
const r = decode(data) as T[];
|
|
1171
1195
|
resolve(r);
|
|
1172
1196
|
} catch (error) {
|
|
1173
1197
|
logger.error(`
|
|
@@ -1188,6 +1212,7 @@ export class SqliteRemoteConnection implements Connection {
|
|
|
1188
1212
|
export class SqliteRemote implements Dao {
|
|
1189
1213
|
[_sqliteRemoteName]: string;
|
|
1190
1214
|
[_daoDB]: SqliteRemoteInterface;
|
|
1215
|
+
private connection?: SqliteRemoteConnection;
|
|
1191
1216
|
|
|
1192
1217
|
constructor(db: SqliteRemoteInterface, name: string) {
|
|
1193
1218
|
this[_daoDB] = db;
|
|
@@ -1203,8 +1228,11 @@ export class SqliteRemote implements Dao {
|
|
|
1203
1228
|
return null;
|
|
1204
1229
|
};
|
|
1205
1230
|
return new Promise<Connection>(async (resolve, reject) => {
|
|
1231
|
+
if (!this.connection) {
|
|
1232
|
+
this.connection = new SqliteRemoteConnection(this[_daoDB], this[_sqliteRemoteName]);
|
|
1233
|
+
}
|
|
1206
1234
|
try {
|
|
1207
|
-
resolve(
|
|
1235
|
+
resolve(this.connection);
|
|
1208
1236
|
} catch (error) {
|
|
1209
1237
|
reject(error);
|
|
1210
1238
|
}
|
|
@@ -1282,24 +1310,24 @@ export type SqlMapper = ([string, string[], any?])[];
|
|
|
1282
1310
|
export type SqlMappers = Record<string, SqlMapper>;
|
|
1283
1311
|
export type SqlModel = Record<string, string | (
|
|
1284
1312
|
(options: {
|
|
1285
|
-
ctx
|
|
1313
|
+
ctx?: any;
|
|
1286
1314
|
isCount?: boolean;
|
|
1287
1315
|
isSum?: boolean;
|
|
1288
1316
|
limitStart?: number;
|
|
1289
1317
|
limitEnd?: number;
|
|
1290
1318
|
orderBy?: string;
|
|
1291
|
-
|
|
1319
|
+
params?: any;
|
|
1292
1320
|
}) => string
|
|
1293
1321
|
)>;
|
|
1294
1322
|
type _SqlModel = Record<string, string | (
|
|
1295
1323
|
(options: {
|
|
1296
|
-
ctx
|
|
1324
|
+
ctx?: any;
|
|
1297
1325
|
isCount?: boolean;
|
|
1298
1326
|
isSum?: boolean;
|
|
1299
1327
|
limitStart?: number;
|
|
1300
1328
|
limitEnd?: number;
|
|
1301
1329
|
orderBy?: string;
|
|
1302
|
-
|
|
1330
|
+
params?: any;
|
|
1303
1331
|
}) => string
|
|
1304
1332
|
) | XML[]>;
|
|
1305
1333
|
class Build {
|
|
@@ -1563,6 +1591,31 @@ class Build {
|
|
|
1563
1591
|
}
|
|
1564
1592
|
};
|
|
1565
1593
|
}
|
|
1594
|
+
/**
|
|
1595
|
+
* * PROBLEM_TYPE = 枚举名
|
|
1596
|
+
* * t.problemtype = 列名
|
|
1597
|
+
*
|
|
1598
|
+
* ```
|
|
1599
|
+
* {{#enumTag}} PROBLEM_TYPE(t.problemtype) {{/enumTag}}
|
|
1600
|
+
* ```
|
|
1601
|
+
*/
|
|
1602
|
+
enum() {
|
|
1603
|
+
return (text: string) => {
|
|
1604
|
+
const matchs = text.match(/([a-zA-Z_]+)\(([^()]+)\)/);
|
|
1605
|
+
if (matchs) {
|
|
1606
|
+
const [_a, MapName, Column] = matchs;
|
|
1607
|
+
if (MapName && Column) {
|
|
1608
|
+
const map = globalThis[_enums].GlobalMap[MapName.trim()];
|
|
1609
|
+
if (map) {
|
|
1610
|
+
return ` CASE
|
|
1611
|
+
${Object.entries(map).map(([k, v]) => `WHEN ${Column} = '${k}' THEN '${v}'`).join(' ')}
|
|
1612
|
+
END `;
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
return "''";
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1566
1619
|
}
|
|
1567
1620
|
|
|
1568
1621
|
function replaceCdata(rawText: string) {
|
|
@@ -1767,7 +1820,7 @@ export class SqlCache {
|
|
|
1767
1820
|
}
|
|
1768
1821
|
}
|
|
1769
1822
|
load(sqlids: string[], options: {
|
|
1770
|
-
ctx
|
|
1823
|
+
ctx?: any;
|
|
1771
1824
|
isCount?: boolean;
|
|
1772
1825
|
isSum?: boolean;
|
|
1773
1826
|
limitStart?: number;
|
|
@@ -1787,17 +1840,12 @@ export class SqlCache {
|
|
|
1787
1840
|
const buildParam = new Build(options.isCount === true, options.isSum === true, options);
|
|
1788
1841
|
if (typeof sqlSource === 'function') {
|
|
1789
1842
|
const _sql = sqlSource(options);
|
|
1790
|
-
|
|
1791
|
-
return format(sql);
|
|
1843
|
+
return mustache.render(_sql, buildParam, this.sqlFNMap);
|
|
1792
1844
|
} else if (typeof sqlSource === 'string') {
|
|
1793
|
-
|
|
1794
|
-
return format(sql);
|
|
1845
|
+
return mustache.render(sqlSource, buildParam, this.sqlFNMap);
|
|
1795
1846
|
} else if (typeof sqlSource === 'object') {
|
|
1796
1847
|
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);
|
|
1848
|
+
return mustache.render(_sql, buildParam, this.sqlFNMap);
|
|
1801
1849
|
}
|
|
1802
1850
|
return '';
|
|
1803
1851
|
}
|
|
@@ -1829,12 +1877,9 @@ function P<T extends object>(skipConn = false) {
|
|
|
1829
1877
|
const option = args[0] = Object.assign({}, globalThis[_GlobalSqlOption], this[_SqlOption], args[0]) as (MethodOption & { sync?: SyncMode; });
|
|
1830
1878
|
option.sync ??= SyncMode.Async;
|
|
1831
1879
|
const dbName = option?.dbName ?? this[_daoDBName] ?? _primaryDB;
|
|
1832
|
-
const dddx = this[_dbType];
|
|
1833
|
-
logger.info(dddx);
|
|
1834
1880
|
option!.dao = globalThis[_dao][this[_dbType]!][dbName] as Dao;
|
|
1835
1881
|
Throw.if(!option!.dao, `not found db:${String(dbName)}(${this[_dbType]})`);
|
|
1836
1882
|
option!.tableName = option?.tableName ?? this[_tableName];
|
|
1837
|
-
const tableES = Sqlstring.escapeId(option!.tableName);
|
|
1838
1883
|
if (this[_dbType] === DBType.Sqlite) {
|
|
1839
1884
|
Throw.if(option.sync === SyncMode.Async, 'sqlite can not Async!')
|
|
1840
1885
|
// 连接共享
|
|
@@ -1843,59 +1888,6 @@ function P<T extends object>(skipConn = false) {
|
|
|
1843
1888
|
} else {
|
|
1844
1889
|
needRealseConn = false;
|
|
1845
1890
|
}
|
|
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
1891
|
try {
|
|
1900
1892
|
const result = fn.call(this, ...args);
|
|
1901
1893
|
logger.info(`${propertyKey}:${option!.tableName}:use ${+new Date() - startTime}ms`);
|
|
@@ -1924,58 +1916,6 @@ function P<T extends object>(skipConn = false) {
|
|
|
1924
1916
|
} else {
|
|
1925
1917
|
needRealseConn = false;
|
|
1926
1918
|
}
|
|
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
1919
|
try {
|
|
1980
1920
|
const result = await fn.call(this, ...args);
|
|
1981
1921
|
logger.info(`${propertyKey}:${option!.tableName}:use ${+new Date() - startTime}ms`);
|
|
@@ -2099,6 +2039,7 @@ export const Field = (config: FieldOption) => {
|
|
|
2099
2039
|
case SqlType.bigint: {
|
|
2100
2040
|
field[DBType.Mysql] = () => `${field.C2()} bigint ${config.notNull === true ? 'NOT NULL' : ''} ${MYSQLCHARSET} ${hasDef ? `DEFAULT '${field.def}'` : ''}`;
|
|
2101
2041
|
field[DBType.SqliteRemote] = field[DBType.Sqlite] = () => `${field.C2()} integer`;
|
|
2042
|
+
field.Data2SQL = (data: any) => BigInt(data ?? 0);
|
|
2102
2043
|
break;
|
|
2103
2044
|
}
|
|
2104
2045
|
case SqlType.float: {
|
|
@@ -2135,26 +2076,31 @@ export const Field = (config: FieldOption) => {
|
|
|
2135
2076
|
case SqlType.date: {
|
|
2136
2077
|
field[DBType.Mysql] = () => `${field.C2()} date ${config.notNull === true ? 'NOT NULL' : ''} ${MYSQLCHARSET} ${hasDef ? `DEFAULT '${field.def}'` : ''}`;
|
|
2137
2078
|
field[DBType.SqliteRemote] = field[DBType.Sqlite] = () => `${field.C2()} text`;
|
|
2079
|
+
field.Data2SQL = (data: any) => typeof data === 'string' ? new Date(data) : data;
|
|
2138
2080
|
break;
|
|
2139
2081
|
}
|
|
2140
2082
|
case SqlType.time: {
|
|
2141
2083
|
field[DBType.Mysql] = () => `${field.C2()} time ${config.notNull === true ? 'NOT NULL' : ''} ${MYSQLCHARSET} ${hasDef ? `DEFAULT '${field.def}'` : ''}`;
|
|
2142
2084
|
field[DBType.SqliteRemote] = field[DBType.Sqlite] = () => `${field.C2()} text`;
|
|
2085
|
+
field.Data2SQL = (data: any) => typeof data === 'string' ? new Date(data) : data;
|
|
2143
2086
|
break;
|
|
2144
2087
|
}
|
|
2145
2088
|
case SqlType.year: {
|
|
2146
2089
|
field[DBType.Mysql] = () => `${field.C2()} year ${config.notNull === true ? 'NOT NULL' : ''} ${MYSQLCHARSET} ${hasDef ? `DEFAULT '${field.def}'` : ''}`;
|
|
2147
2090
|
field[DBType.SqliteRemote] = field[DBType.Sqlite] = () => `${field.C2()} text`;
|
|
2091
|
+
field.Data2SQL = (data: any) => typeof data === 'string' ? new Date(data) : data;
|
|
2148
2092
|
break;
|
|
2149
2093
|
}
|
|
2150
2094
|
case SqlType.datetime: {
|
|
2151
2095
|
field[DBType.Mysql] = () => `${field.C2()} datetime ${config.notNull === true ? 'NOT NULL' : ''} ${MYSQLCHARSET} ${hasDef ? `DEFAULT '${field.def}'` : ''}`;
|
|
2152
2096
|
field[DBType.SqliteRemote] = field[DBType.Sqlite] = () => `${field.C2()} text`;
|
|
2097
|
+
field.Data2SQL = (data: any) => typeof data === 'string' ? new Date(data) : data;
|
|
2153
2098
|
break;
|
|
2154
2099
|
}
|
|
2155
2100
|
case SqlType.timestamp: {
|
|
2156
2101
|
field[DBType.Mysql] = () => `${field.C2()} timestamp ${config.notNull === true ? 'NOT NULL' : ''} ${MYSQLCHARSET} ${hasDef ? `DEFAULT '${field.def}'` : ''}`;
|
|
2157
2102
|
field[DBType.SqliteRemote] = field[DBType.Sqlite] = () => `${field.C2()} integer`;
|
|
2103
|
+
field.Data2SQL = (data: any) => typeof data === 'string' ? +new Date(data) : data;
|
|
2158
2104
|
break;
|
|
2159
2105
|
}
|
|
2160
2106
|
case SqlType.char: {
|
|
@@ -2269,6 +2215,7 @@ export const Field = (config: FieldOption) => {
|
|
|
2269
2215
|
let __columns = Reflect.getMetadata(_columns, object);
|
|
2270
2216
|
let __columnsNoId = Reflect.getMetadata(_columnsNoId, object);
|
|
2271
2217
|
let __ids = Reflect.getMetadata(_ids, object);
|
|
2218
|
+
let __logicIds = Reflect.getMetadata(_logicIds, object);
|
|
2272
2219
|
let __index = Reflect.getMetadata(_index, object);
|
|
2273
2220
|
let __def = Reflect.getMetadata(_def, object);
|
|
2274
2221
|
|
|
@@ -2287,16 +2234,23 @@ export const Field = (config: FieldOption) => {
|
|
|
2287
2234
|
} else {
|
|
2288
2235
|
__columnsNoId.push(propertyName);
|
|
2289
2236
|
}
|
|
2237
|
+
if (field.logicId === true) {
|
|
2238
|
+
__logicIds.push(propertyName);
|
|
2239
|
+
}
|
|
2290
2240
|
if (field.index === true) {
|
|
2291
2241
|
__index.push(propertyName);
|
|
2292
2242
|
}
|
|
2293
2243
|
if (hasDef) {
|
|
2294
2244
|
__def[propertyName] = field.def;
|
|
2295
2245
|
}
|
|
2246
|
+
if (field.comment) {
|
|
2247
|
+
__def[propertyName] = field.comment;
|
|
2248
|
+
}
|
|
2296
2249
|
Reflect.defineMetadata(_fields, __fields, object);
|
|
2297
2250
|
Reflect.defineMetadata(_columns, __columns, object);
|
|
2298
2251
|
Reflect.defineMetadata(_columnsNoId, __columnsNoId, object);
|
|
2299
2252
|
Reflect.defineMetadata(_ids, __ids, object);
|
|
2253
|
+
Reflect.defineMetadata(_logicIds, __logicIds, object);
|
|
2300
2254
|
Reflect.defineMetadata(_index, __index, object);
|
|
2301
2255
|
Reflect.defineMetadata(_def, __def, object);
|
|
2302
2256
|
if (field.hasOwnProperty('logicDelete')) {
|
|
@@ -2305,16 +2259,24 @@ export const Field = (config: FieldOption) => {
|
|
|
2305
2259
|
}
|
|
2306
2260
|
};
|
|
2307
2261
|
}
|
|
2262
|
+
const formatDialects = {
|
|
2263
|
+
[DBType.Mysql]: mysql,
|
|
2264
|
+
[DBType.Sqlite]: sqlite,
|
|
2265
|
+
[DBType.SqliteRemote]: sqlite
|
|
2266
|
+
};
|
|
2308
2267
|
export const DB = (config: ServiceOption) => {
|
|
2309
2268
|
return function <C extends { new(...args: any[]): {} }>(constructor: C) {
|
|
2310
2269
|
const __ids = Reflect.getMetadata(_ids, config.clz.prototype) || new Array<string>;
|
|
2270
|
+
const __logicIds = Reflect.getMetadata(_logicIds, config.clz.prototype) || new Array<string>;
|
|
2311
2271
|
const __fields = Reflect.getMetadata(_fields, config.clz.prototype);
|
|
2312
2272
|
const __columns = Reflect.getMetadata(_columns, config.clz.prototype);
|
|
2313
|
-
const __columnsNoId =
|
|
2273
|
+
const __columnsNoId = Reflect.getMetadata(_columnsNoId, config.clz.prototype);
|
|
2314
2274
|
const __stateFileName = Reflect.getMetadata(_stateFileName, config.clz.prototype);
|
|
2315
2275
|
const __deleteState = Reflect.getMetadata(_deleteState, config.clz.prototype);
|
|
2316
2276
|
const __index = Reflect.getMetadata(_index, config.clz.prototype);
|
|
2317
2277
|
const __def = Reflect.getMetadata(_def, config.clz.prototype);
|
|
2278
|
+
const __dbType = config.dbType ?? DBType.Mysql;
|
|
2279
|
+
const __formatDialect = formatDialects[__dbType];
|
|
2318
2280
|
const className = config.tableName?.replace(/_(\w)/g, (a: string, b: string) => b.toUpperCase());
|
|
2319
2281
|
const ClassName = className?.replace(/\w/, (v: string) => v.toUpperCase());
|
|
2320
2282
|
const vueName = config.tableName?.replace(/_/g, '-');
|
|
@@ -2323,17 +2285,21 @@ export const DB = (config: ServiceOption) => {
|
|
|
2323
2285
|
[_className] = className;
|
|
2324
2286
|
[_ClassName] = ClassName;
|
|
2325
2287
|
[_vueName] = vueName;
|
|
2288
|
+
|
|
2326
2289
|
[_daoDBName] = config.dbName;
|
|
2327
|
-
[_dbType] =
|
|
2290
|
+
[_dbType] = __dbType;
|
|
2291
|
+
[_formatDialect] = __formatDialect;
|
|
2328
2292
|
[_sqlite_version] = config.sqliteVersion;
|
|
2329
2293
|
[_SqlOption] = Object.assign({}, _defOption, config);
|
|
2330
2294
|
|
|
2331
2295
|
[_ids] = __ids;
|
|
2296
|
+
[_logicIds] = __logicIds;
|
|
2332
2297
|
[_fields] = __fields;
|
|
2333
2298
|
[_columns] = __columns;
|
|
2334
2299
|
[_columnsNoId] = __columnsNoId;
|
|
2335
2300
|
[_index] = __index;
|
|
2336
2301
|
[_def] = __def;
|
|
2302
|
+
[_comment] = config.comment;
|
|
2337
2303
|
[_stateFileName] = __stateFileName;
|
|
2338
2304
|
[_deleteState] = __deleteState;
|
|
2339
2305
|
|
|
@@ -2355,6 +2321,9 @@ export const DB = (config: ServiceOption) => {
|
|
|
2355
2321
|
.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
2322
|
.filter(data => {
|
|
2357
2323
|
if ((data[1] as any)[0] === 1) {
|
|
2324
|
+
if (__fields[data[0] as string].Data2SQL) {
|
|
2325
|
+
(data[1] as any)[1] = __fields[data[0] as string].Data2SQL((data[1] as any)[1]);
|
|
2326
|
+
}
|
|
2358
2327
|
if (option?.onFieldExists) {
|
|
2359
2328
|
option.onFieldExists(data[0] as string, (data[1] as any)[1]);
|
|
2360
2329
|
}
|
|
@@ -2418,7 +2387,9 @@ export class SqlService<T extends object> {
|
|
|
2418
2387
|
private [_ClassName]?: string;
|
|
2419
2388
|
private [_vueName]?: string;
|
|
2420
2389
|
private [_daoDBName]?: string;
|
|
2390
|
+
private [_comment]?: string;
|
|
2421
2391
|
private [_ids]?: string[];
|
|
2392
|
+
// private [_logicIds]?: string[];
|
|
2422
2393
|
private [_fields]?: Record<string, AField>;
|
|
2423
2394
|
private [_columns]?: string[];
|
|
2424
2395
|
private [_columnsNoId]?: string[];
|
|
@@ -2426,6 +2397,7 @@ export class SqlService<T extends object> {
|
|
|
2426
2397
|
private [_deleteState]?: string;
|
|
2427
2398
|
private [_SqlOption]?: ServiceOption;
|
|
2428
2399
|
private [_dbType]?: DBType;
|
|
2400
|
+
private [_formatDialect]?: DialectOptions;
|
|
2429
2401
|
private [_sqlite_version]?: string;
|
|
2430
2402
|
private [_index]?: string[];
|
|
2431
2403
|
private [_def]?: Partial<T>;
|
|
@@ -2445,6 +2417,7 @@ export class SqlService<T extends object> {
|
|
|
2445
2417
|
existConditionOtherThanIds?: (keyof T)[];
|
|
2446
2418
|
replaceWithDef?: boolean;
|
|
2447
2419
|
}): { sql: string; params?: any[] }[] {
|
|
2420
|
+
|
|
2448
2421
|
const sqls: { sql: string; params?: any[] }[] = [];
|
|
2449
2422
|
const tableName = Sqlstring.escapeId(option!.tableName);
|
|
2450
2423
|
switch (option?.mode) {
|
|
@@ -2493,10 +2466,10 @@ export class SqlService<T extends object> {
|
|
|
2493
2466
|
return `SELECT ${questMark.join(',')} FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM ${tableName} WHERE ${where})`;
|
|
2494
2467
|
});
|
|
2495
2468
|
const columnNames = iterare<string>(finalColumns).map(i => this[_fields]![i]?.C2()).join(',');
|
|
2496
|
-
const sql =
|
|
2469
|
+
const sql = formatDialect(`INSERT INTO
|
|
2497
2470
|
${tableName}
|
|
2498
2471
|
(${columnNames})
|
|
2499
|
-
${questMarks.join(' UNION ALL ')}
|
|
2472
|
+
${questMarks.join(' UNION ALL ')};`, { dialect: this[_formatDialect]! });
|
|
2500
2473
|
sqls.push({ sql, params });
|
|
2501
2474
|
break;
|
|
2502
2475
|
}
|
|
@@ -2531,12 +2504,12 @@ export class SqlService<T extends object> {
|
|
|
2531
2504
|
return `(${questMark.join(',')})`;
|
|
2532
2505
|
});
|
|
2533
2506
|
const columnNames = iterare(finalColumns).map(i => this[_fields]![i]?.C2()).join(',');
|
|
2534
|
-
const sql =
|
|
2507
|
+
const sql = formatDialect(`
|
|
2535
2508
|
${this[_dbType] === DBType.Mysql ? '' : 'INSERT OR'} REPLACE INTO
|
|
2536
2509
|
${tableName}
|
|
2537
2510
|
(${columnNames})
|
|
2538
2511
|
VALUES ${questMarks};
|
|
2539
|
-
|
|
2512
|
+
`, { dialect: this[_formatDialect]! });
|
|
2540
2513
|
sqls.push({ sql, params });
|
|
2541
2514
|
break;
|
|
2542
2515
|
}
|
|
@@ -2571,12 +2544,12 @@ export class SqlService<T extends object> {
|
|
|
2571
2544
|
return `(${questMark.join(',')})`;
|
|
2572
2545
|
});
|
|
2573
2546
|
const columnNames = iterare(finalColumns).map(i => this[_fields]![i]?.C2()).join(',');
|
|
2574
|
-
const sql =
|
|
2547
|
+
const sql = formatDialect(`
|
|
2575
2548
|
INSERT INTO
|
|
2576
2549
|
${tableName}
|
|
2577
2550
|
(${columnNames})
|
|
2578
2551
|
VALUES ${questMarks};
|
|
2579
|
-
|
|
2552
|
+
`, { dialect: this[_formatDialect]! });
|
|
2580
2553
|
|
|
2581
2554
|
sqls.push({ sql, params });
|
|
2582
2555
|
break;
|
|
@@ -2618,16 +2591,16 @@ export class SqlService<T extends object> {
|
|
|
2618
2591
|
sqls.push(..._sqls);
|
|
2619
2592
|
const columnNames = iterare(finalColumns).map(i => this[_fields]![i]?.C2()).join(',');
|
|
2620
2593
|
sqls.push({
|
|
2621
|
-
sql:
|
|
2594
|
+
sql: formatDialect(`
|
|
2622
2595
|
INSERT INTO
|
|
2623
2596
|
${tableTemp}
|
|
2624
2597
|
(${columnNames})
|
|
2625
2598
|
VALUES ${questMarks};
|
|
2626
|
-
|
|
2599
|
+
`, { dialect: this[_formatDialect]! }), params
|
|
2627
2600
|
});
|
|
2628
2601
|
sqls.push({
|
|
2629
|
-
sql:
|
|
2630
|
-
SELECT ${columnNames} FROM ${tableTemp}
|
|
2602
|
+
sql: formatDialect(`INSERT INTO ${Sqlstring.escapeId(option.tableName)} (${columnNames})
|
|
2603
|
+
SELECT ${columnNames} FROM ${tableTemp};`, { dialect: this[_formatDialect]! })
|
|
2631
2604
|
});
|
|
2632
2605
|
sqls.push({ sql: `DROP TABLE IF EXISTS ${tableTempESC};` });
|
|
2633
2606
|
break;
|
|
@@ -2698,23 +2671,21 @@ export class SqlService<T extends object> {
|
|
|
2698
2671
|
}
|
|
2699
2672
|
} else if (isArray) {
|
|
2700
2673
|
const fn = async () => {
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
return result;
|
|
2717
|
-
}, option?.conn);
|
|
2674
|
+
const result = await excuteSplit<Partial<T>, bigint>(
|
|
2675
|
+
ExcuteSplitMode.AsyncTrust,
|
|
2676
|
+
datas,
|
|
2677
|
+
async _data => {
|
|
2678
|
+
const sqls = this._insert(_data, option);
|
|
2679
|
+
let result = 0n;
|
|
2680
|
+
for (const { sql, params } of sqls) {
|
|
2681
|
+
const dd = await option!.conn!.execute(SyncMode.Async, sql, params);
|
|
2682
|
+
if (dd.insertId) { result += dd.insertId; }
|
|
2683
|
+
}
|
|
2684
|
+
return result;
|
|
2685
|
+
},
|
|
2686
|
+
{ everyLength: option?.every === true ? 1 : option?.maxDeal }
|
|
2687
|
+
);
|
|
2688
|
+
return result;
|
|
2718
2689
|
};
|
|
2719
2690
|
return new Promise<bigint[]>(async (resolve, reject) => {
|
|
2720
2691
|
try {
|
|
@@ -2787,13 +2758,13 @@ export class SqlService<T extends object> {
|
|
|
2787
2758
|
}
|
|
2788
2759
|
);
|
|
2789
2760
|
}
|
|
2790
|
-
const sql =
|
|
2761
|
+
const sql = formatDialect(`UPDATE ${tableName} SET ${iterare(this[_columnsNoId]!)
|
|
2791
2762
|
.filter(K => columnMaps[K]!.where.length > 0)
|
|
2792
2763
|
.map(K => {
|
|
2793
2764
|
params.push(...columnMaps[K]!.params);
|
|
2794
2765
|
return `${this[_fields]![K]?.C2()} = CASE ${columnMaps[K]!.where.join(' ')} ELSE ${this[_fields]![K]?.C2()} END`
|
|
2795
2766
|
})
|
|
2796
|
-
.join(',')}
|
|
2767
|
+
.join(',')};`, { dialect: this[_formatDialect]! });
|
|
2797
2768
|
sqls.push({ sql, params });
|
|
2798
2769
|
return sqls;
|
|
2799
2770
|
}
|
|
@@ -2939,13 +2910,13 @@ export class SqlService<T extends object> {
|
|
|
2939
2910
|
if (this[_stateFileName] !== undefined && option.forceDelete !== true) {
|
|
2940
2911
|
params.unshift(this[_deleteState]);
|
|
2941
2912
|
sqls.push({
|
|
2942
|
-
sql:
|
|
2913
|
+
sql: formatDialect(`
|
|
2943
2914
|
UPDATE ${tableNameESC} SET ${this[_fields]![this[_stateFileName]]?.C2()} = ?
|
|
2944
2915
|
WHERE ${whereSql};
|
|
2945
|
-
|
|
2916
|
+
`, { dialect: this[_formatDialect]! }), params
|
|
2946
2917
|
});
|
|
2947
2918
|
} else {
|
|
2948
|
-
sqls.push({ sql:
|
|
2919
|
+
sqls.push({ sql: formatDialect(`DELETE FROM ${tableNameESC} WHERE ${whereSql};`, { dialect: this[_formatDialect]! }), params });
|
|
2949
2920
|
}
|
|
2950
2921
|
} else {
|
|
2951
2922
|
sqls.push({ sql: `DROP TABLE IF EXISTS ${tableTempESC};` });
|
|
@@ -2956,13 +2927,13 @@ export class SqlService<T extends object> {
|
|
|
2956
2927
|
case DBType.Mysql: {
|
|
2957
2928
|
if (this[_stateFileName] !== undefined && option.forceDelete !== true) {
|
|
2958
2929
|
sqls.push({
|
|
2959
|
-
sql:
|
|
2960
|
-
SET a.${this[_fields]![this[_stateFileName]]?.C2()} =
|
|
2930
|
+
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 ')}
|
|
2931
|
+
SET a.${this[_fields]![this[_stateFileName]]?.C2()} = ?;`, { dialect: this[_formatDialect]! }),
|
|
2961
2932
|
params: [this[_deleteState]]
|
|
2962
2933
|
});
|
|
2963
2934
|
} else {
|
|
2964
2935
|
sqls.push({
|
|
2965
|
-
sql:
|
|
2936
|
+
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
2937
|
});
|
|
2967
2938
|
}
|
|
2968
2939
|
break;
|
|
@@ -2972,12 +2943,12 @@ export class SqlService<T extends object> {
|
|
|
2972
2943
|
const columnNames = iterare(delWhere).map(K => this[_fields]![K]?.C2()).join(',');
|
|
2973
2944
|
if (this[_stateFileName] !== undefined && option.forceDelete !== true) {
|
|
2974
2945
|
sqls.push({
|
|
2975
|
-
sql:
|
|
2976
|
-
WHERE (${columnNames}) IN (SELECT ${columnNames} FROM ${tableTempESC})
|
|
2946
|
+
sql: formatDialect(`UPDATE ${tableNameESC} SET ${this[_fields]![this[_stateFileName]]?.C2()} = ?
|
|
2947
|
+
WHERE (${columnNames}) IN (SELECT ${columnNames} FROM ${tableTempESC});`, { dialect: this[_formatDialect]! }),
|
|
2977
2948
|
params: [this[_deleteState]]
|
|
2978
2949
|
});
|
|
2979
2950
|
} else {
|
|
2980
|
-
sqls.push({ sql:
|
|
2951
|
+
sqls.push({ sql: formatDialect(`DELETE FROM ${tableNameESC} WHERE (${columnNames}) IN (SELECT ${columnNames} FROM ${tableTempESC});`, { dialect: this[_formatDialect]! }) });
|
|
2981
2952
|
}
|
|
2982
2953
|
break;
|
|
2983
2954
|
}
|
|
@@ -3102,13 +3073,13 @@ export class SqlService<T extends object> {
|
|
|
3102
3073
|
let resultIndex = -1;
|
|
3103
3074
|
if (option.mode === SelectMode.Common) {
|
|
3104
3075
|
const params = new Array<any>();
|
|
3105
|
-
const whereSql =
|
|
3076
|
+
const whereSql = formatDialect(iterare(wheres).map(where => this[_transformer]!(where, option)).map(where => {
|
|
3106
3077
|
return `SELECT ${columns} FROM ${tableNameESC} a WHERE
|
|
3107
3078
|
${Object.entries(where).map(([K, V]) => {
|
|
3108
3079
|
params.push(V);
|
|
3109
3080
|
return `${this[_fields]![K]?.C2()} = ?`;
|
|
3110
3081
|
}).join(' AND ')}`;
|
|
3111
|
-
}).join(' UNION ALL '));
|
|
3082
|
+
}).join(' UNION ALL '), { dialect: this[_formatDialect]! });
|
|
3112
3083
|
sqls.push({ sql: whereSql, params });
|
|
3113
3084
|
resultIndex = 0;
|
|
3114
3085
|
} else {
|
|
@@ -3117,7 +3088,7 @@ export class SqlService<T extends object> {
|
|
|
3117
3088
|
const _sqls = this._createTable<L>({ tableName: tableTemp, temp: true, columns: delWhere, data: wheres, index: 'all', id: 'none' })!;
|
|
3118
3089
|
sqls.push(..._sqls);
|
|
3119
3090
|
resultIndex = sqls.length;
|
|
3120
|
-
sqls.push({ sql:
|
|
3091
|
+
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
3092
|
sqls.push({ sql: `DROP TABLE IF EXISTS ${tableTempESC};` });
|
|
3122
3093
|
}
|
|
3123
3094
|
|
|
@@ -3270,7 +3241,7 @@ export class SqlService<T extends object> {
|
|
|
3270
3241
|
const _params = Object.assign({}, option.context, option.params);
|
|
3271
3242
|
option.sql ??= globalThis[_sqlCache].load(this._matchSqlid(option.sqlId), { ctx: option.context, isCount: option.isCount, ..._params });
|
|
3272
3243
|
const params: any[] = [];
|
|
3273
|
-
const sql = option.sql?.replace(/\:([A-Za-z0-9._]+)/g, (txt, key) => {
|
|
3244
|
+
const sql = formatDialect(option.sql?.replace(/\:([A-Za-z0-9._]+)/g, (txt, key) => {
|
|
3274
3245
|
let V = LGet(_params, key);
|
|
3275
3246
|
if (V) {
|
|
3276
3247
|
if (V !== undefined) {
|
|
@@ -3295,7 +3266,7 @@ export class SqlService<T extends object> {
|
|
|
3295
3266
|
return '?';
|
|
3296
3267
|
}
|
|
3297
3268
|
return txt;
|
|
3298
|
-
});
|
|
3269
|
+
})!, { dialect: this[_formatDialect]! });
|
|
3299
3270
|
if (option.sync === SyncMode.Sync) {
|
|
3300
3271
|
const result = option!.conn!.query(SyncMode.Sync, sql, params);
|
|
3301
3272
|
return this._select<L>(option.selectResult, result, option.defValue, option.errorMsg, option.hump, option.mapper, option.mapperIfUndefined);
|
|
@@ -3334,7 +3305,7 @@ export class SqlService<T extends object> {
|
|
|
3334
3305
|
const _params = Object.assign({}, option.context, option.params);
|
|
3335
3306
|
option.sql ??= globalThis[_sqlCache].load(this._matchSqlid(option.sqlId), { ctx: option.context, ..._params });
|
|
3336
3307
|
const params: any[] = [];
|
|
3337
|
-
const sql = option.sql?.replace(/\:(\w+)/g, (txt, key) => {
|
|
3308
|
+
const sql = formatDialect(option.sql?.replace(/\:(\w+)/g, (txt, key) => {
|
|
3338
3309
|
let V = LGet(_params, key);
|
|
3339
3310
|
if (V) {
|
|
3340
3311
|
if (V !== undefined) {
|
|
@@ -3359,7 +3330,7 @@ export class SqlService<T extends object> {
|
|
|
3359
3330
|
return '?';
|
|
3360
3331
|
}
|
|
3361
3332
|
return txt;
|
|
3362
|
-
});
|
|
3333
|
+
})!, { dialect: this[_formatDialect]! });
|
|
3363
3334
|
if (option.sync === SyncMode.Sync) {
|
|
3364
3335
|
const result = option!.conn!.execute(SyncMode.Sync, sql, params);
|
|
3365
3336
|
return result.affectedRows;
|
|
@@ -3414,17 +3385,18 @@ export class SqlService<T extends object> {
|
|
|
3414
3385
|
return new StreamQuery<L>(option?.tableName ?? this[_tableName]!, this as any, this[_fields]!, this[_columns]!);
|
|
3415
3386
|
}
|
|
3416
3387
|
|
|
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>;
|
|
3388
|
+
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>>;
|
|
3389
|
+
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
3390
|
@P<T>()
|
|
3421
|
-
page<L = T>(option: MethodOption & { sync?: SyncMode; sqlId: string; context?: any; params: Record<string, any>; pageSize
|
|
3391
|
+
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
3392
|
const result: PageQuery<L> = {
|
|
3423
3393
|
sum: {},
|
|
3424
3394
|
records: [],
|
|
3425
3395
|
size: 0,
|
|
3426
3396
|
total: 0
|
|
3427
3397
|
};
|
|
3398
|
+
option.pageNumber ??= 1;
|
|
3399
|
+
option.pageSize ??= 0;
|
|
3428
3400
|
Object.assign(option.params, {
|
|
3429
3401
|
limitStart: calc(option.pageNumber).sub(1).mul(option.pageSize).over(),
|
|
3430
3402
|
limitEnd: calc(option.pageSize).over(),
|
|
@@ -3495,7 +3467,7 @@ export class SqlService<T extends object> {
|
|
|
3495
3467
|
selectResult: SelectResult.R_C_Assert
|
|
3496
3468
|
});
|
|
3497
3469
|
result.size = calc(result.total)
|
|
3498
|
-
.add(option.pageSize - 1)
|
|
3470
|
+
.add(option.pageSize ?? 10 - 1)
|
|
3499
3471
|
.div(option.pageSize)
|
|
3500
3472
|
.round(0, 2)
|
|
3501
3473
|
.over();
|
|
@@ -3524,6 +3496,177 @@ export class SqlService<T extends object> {
|
|
|
3524
3496
|
}
|
|
3525
3497
|
}
|
|
3526
3498
|
|
|
3499
|
+
/**
|
|
3500
|
+
* 导出数据,可以为EJS-EXCEL直接使用
|
|
3501
|
+
* @param list
|
|
3502
|
+
* @returns
|
|
3503
|
+
*/
|
|
3504
|
+
exp<L = T>(list: L[]) {
|
|
3505
|
+
Throw.if(list.length === 0, 'not found data!');
|
|
3506
|
+
const columnTitles = new Array<string>();
|
|
3507
|
+
const keys = this[_fields] ?
|
|
3508
|
+
iterare(Object.entries(this[_fields]))
|
|
3509
|
+
.filter(([K, F]) => (F.id !== true && F.exportable !== false) || (F.id === true && F.exportable === true))
|
|
3510
|
+
.map(([K, F]) => {
|
|
3511
|
+
columnTitles.push(F.comment ?? K);
|
|
3512
|
+
return K;
|
|
3513
|
+
}).toArray()
|
|
3514
|
+
: Object.keys(list[0]!).filter(K => !this[_ids]?.includes(K));
|
|
3515
|
+
const title = this[_comment] ?? this[_tableName];
|
|
3516
|
+
const titleSpan = `A1:${ten2Any(keys.length)}1`;
|
|
3517
|
+
const datas = list.map(data => keys.map(k => data[k] ?? ''));
|
|
3518
|
+
return { title, titleSpan, columnTitles, datas };
|
|
3519
|
+
}
|
|
3520
|
+
/**
|
|
3521
|
+
* 导入数据的模板
|
|
3522
|
+
* @returns
|
|
3523
|
+
*/
|
|
3524
|
+
imp() {
|
|
3525
|
+
Throw.if(!this[_fields], 'not set fields!');
|
|
3526
|
+
const columnTitles = new Array<string>();
|
|
3527
|
+
const keys = iterare(Object.entries(this[_fields]!))
|
|
3528
|
+
.filter(([K, F]) => (F.id !== true && F.exportable !== false) || (F.id === true && F.exportable === true))
|
|
3529
|
+
.map(([K, F]) => {
|
|
3530
|
+
columnTitles.push(F.comment ?? K);
|
|
3531
|
+
return K;
|
|
3532
|
+
}).toArray();
|
|
3533
|
+
const title = this[_comment] ?? this[_tableName];
|
|
3534
|
+
const titleSpan = `A1:${ten2Any(keys.length)}1`;
|
|
3535
|
+
return { title, titleSpan, columnTitles };
|
|
3536
|
+
}
|
|
3537
|
+
|
|
3538
|
+
/**
|
|
3539
|
+
* 初始化表结构
|
|
3540
|
+
* 只有sqlite、sqliteremote需要
|
|
3541
|
+
* force: 是否强制,默认false, 强制时会删除再创建
|
|
3542
|
+
* @param option
|
|
3543
|
+
*/
|
|
3544
|
+
init(option?: MethodOption & { sync?: SyncMode.Async; force?: boolean }): Promise<void>;
|
|
3545
|
+
init(option: MethodOption & { sync: SyncMode.Sync; force?: boolean }): void;
|
|
3546
|
+
@P<T>()
|
|
3547
|
+
init(option?: MethodOption & { sync?: SyncMode; force?: boolean }): void | Promise<void> {
|
|
3548
|
+
const tableES = Sqlstring.escapeId(option!.tableName);
|
|
3549
|
+
option!.force ??= false;
|
|
3550
|
+
if (this[_dbType] === DBType.Sqlite) {
|
|
3551
|
+
if (option?.force) {
|
|
3552
|
+
option!.conn!.execute(SyncMode.Sync, `DROP TABLE IF EXISTS ${tableES};`);
|
|
3553
|
+
}
|
|
3554
|
+
const lastVersion = this[_sqlite_version] ?? '0.0.1';
|
|
3555
|
+
// 检查表
|
|
3556
|
+
const tableCheckResult = option!.conn!.pluck<number>(SyncMode.Sync, `SELECT COUNT(1) t FROM sqlite_master WHERE TYPE = 'table' AND name = ?`, [option!.tableName]);
|
|
3557
|
+
if (tableCheckResult) {
|
|
3558
|
+
// 旧版本
|
|
3559
|
+
const tableVersion = option!.conn!.pluck<string>(SyncMode.Sync, 'SELECT ______version v from TABLE_VERSION WHERE ______tableName = ?', [option!.tableName]);
|
|
3560
|
+
if (tableVersion && tableVersion < lastVersion) { // 发现需要升级的版本
|
|
3561
|
+
// 更新版本
|
|
3562
|
+
const columns = iterare<{ name: string }>(option!.conn!.query(SyncMode.Sync, `PRAGMA table_info(${tableES})`))
|
|
3563
|
+
.filter(c => this[_fields]!.hasOwnProperty(C2P(c.name, globalThis[_Hump])))
|
|
3564
|
+
.map(c => Sqlstring.escapeId(c.name))
|
|
3565
|
+
.join(',');
|
|
3566
|
+
|
|
3567
|
+
const rtable = Sqlstring.escapeId(`${option!.tableName}_${tableVersion.replace(/\./, '_')}`);
|
|
3568
|
+
option!.conn!.execute(SyncMode.Sync, `DROP TABLE IF EXISTS ${rtable};`);
|
|
3569
|
+
option!.conn!.execute(SyncMode.Sync, `ALTER TABLE ${tableES} RENAME TO ${rtable};`);
|
|
3570
|
+
option!.conn!.execute(SyncMode.Sync, `
|
|
3571
|
+
CREATE TABLE IF NOT EXISTS ${tableES}(
|
|
3572
|
+
${Object.values(this[_fields]!).map(K => K[DBType.Sqlite]()).join(',')}
|
|
3573
|
+
${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields]![i]?.C2()).join(',')})` : ''}
|
|
3574
|
+
);
|
|
3575
|
+
`);
|
|
3576
|
+
if (this[_index] && this[_index].length) {
|
|
3577
|
+
for (const index of this[_index]) {
|
|
3578
|
+
option!.conn!.execute(SyncMode.Sync, `CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${tableES} ("${this[_fields]![index]?.C2()}");`);
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3581
|
+
option!.conn!.execute(SyncMode.Sync, `INSERT INTO ${tableES} (${columns}) SELECT ${columns} FROM ${rtable};`);
|
|
3582
|
+
option!.conn!.execute(SyncMode.Sync, `INSERT INTO ${tableES} (${columns}) SELECT ${columns} FROM ${rtable};`);
|
|
3583
|
+
option!.conn!.execute(SyncMode.Sync, `DROP TABLE IF EXISTS ${rtable};`);
|
|
3584
|
+
// 更新完毕,保存版本号
|
|
3585
|
+
option!.conn!.execute(SyncMode.Sync, 'UPDATE TABLE_VERSION SET ______version = ? WHERE ______tableName = ?', [option!.tableName, lastVersion]);
|
|
3586
|
+
} else if (!tableVersion) { // 不需要升级情况:没有旧的版本号
|
|
3587
|
+
option!.conn!.execute(SyncMode.Sync, 'INSERT INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option!.tableName, lastVersion]);
|
|
3588
|
+
}
|
|
3589
|
+
} else { // 表不存在
|
|
3590
|
+
// 创建表
|
|
3591
|
+
option!.conn!.execute(SyncMode.Sync, `
|
|
3592
|
+
CREATE TABLE IF NOT EXISTS ${tableES} (
|
|
3593
|
+
${Object.values(this[_fields]!).map(K => K[DBType.Sqlite]()).join(',')}
|
|
3594
|
+
${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields]![i]?.C2()).join(',')})` : ''}
|
|
3595
|
+
|
|
3596
|
+
);
|
|
3597
|
+
`);
|
|
3598
|
+
if (this[_index] && this[_index].length) {
|
|
3599
|
+
for (const index of this[_index]) {
|
|
3600
|
+
option!.conn!.execute(SyncMode.Sync, `CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${tableES} ("${this[_fields]![index]?.C2()}");`);
|
|
3601
|
+
}
|
|
3602
|
+
}
|
|
3603
|
+
option!.conn!.execute(SyncMode.Sync, 'INSERT OR REPLACE INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option!.tableName, lastVersion]);
|
|
3604
|
+
}
|
|
3605
|
+
} else if (this[_dbType] === DBType.SqliteRemote) {
|
|
3606
|
+
|
|
3607
|
+
return new Promise(async (resolve, reject) => {
|
|
3608
|
+
try {
|
|
3609
|
+
if (option?.force) {
|
|
3610
|
+
await option!.conn!.execute(SyncMode.Async, `DROP TABLE IF EXISTS ${tableES};`);
|
|
3611
|
+
}
|
|
3612
|
+
const lastVersion = this[_sqlite_version] ?? '0.0.1';
|
|
3613
|
+
// 检查表
|
|
3614
|
+
const tableCheckResult = await option!.conn!.pluck<number>(SyncMode.Async, `SELECT COUNT(1) t FROM sqlite_master WHERE TYPE = 'table' AND name = ?`, [option!.tableName]);
|
|
3615
|
+
if (tableCheckResult) {
|
|
3616
|
+
// 旧版本
|
|
3617
|
+
const tableVersion = await option!.conn!.pluck<string>(SyncMode.Async, 'SELECT ______version v from TABLE_VERSION WHERE ______tableName = ?', [option!.tableName]);
|
|
3618
|
+
if (tableVersion && tableVersion < lastVersion) { // 发现需要升级的版本
|
|
3619
|
+
// 更新版本
|
|
3620
|
+
const columns = iterare<{ name: string }>(await option!.conn!.query(SyncMode.Async, `PRAGMA table_info(${tableES})`))
|
|
3621
|
+
.filter(c => this[_fields]!.hasOwnProperty(C2P(c.name, globalThis[_Hump])))
|
|
3622
|
+
.map(c => Sqlstring.escapeId(c.name))
|
|
3623
|
+
.join(',');
|
|
3624
|
+
|
|
3625
|
+
const rtable = `${option!.tableName}_${tableVersion.replace(/\./, '_')}`;
|
|
3626
|
+
await option!.conn!.execute(SyncMode.Async, `DROP TABLE IF EXISTS ${rtable};`);
|
|
3627
|
+
await option!.conn!.execute(SyncMode.Async, `ALTER TABLE ${tableES} RENAME TO ${rtable};`);
|
|
3628
|
+
await option!.conn!.execute(SyncMode.Async, `
|
|
3629
|
+
CREATE TABLE IF NOT EXISTS ${tableES}(
|
|
3630
|
+
${Object.values(this[_fields]!).map(K => K[DBType.Sqlite]()).join(',')}
|
|
3631
|
+
${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields]![i]?.C2()).join(',')})` : ''}
|
|
3632
|
+
);
|
|
3633
|
+
`);
|
|
3634
|
+
if (this[_index] && this[_index].length) {
|
|
3635
|
+
for (const index of this[_index]) {
|
|
3636
|
+
await option!.conn!.execute(SyncMode.Async, `CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${tableES} ("${this[_fields]![index]?.C2()}");`);
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3639
|
+
await option!.conn!.execute(SyncMode.Async, `INSERT INTO ${tableES} (${columns}) SELECT ${columns} FROM ${rtable};`);
|
|
3640
|
+
await option!.conn!.execute(SyncMode.Async, `INSERT INTO ${tableES} (${columns}) SELECT ${columns} FROM ${rtable};`);
|
|
3641
|
+
await option!.conn!.execute(SyncMode.Async, `DROP TABLE IF EXISTS ${rtable};`);
|
|
3642
|
+
// 更新完毕,保存版本号
|
|
3643
|
+
await option!.conn!.execute(SyncMode.Async, 'UPDATE TABLE_VERSION SET ______version = ? WHERE ______tableName = ?', [option!.tableName, lastVersion]);
|
|
3644
|
+
} else if (!tableVersion) { // 不需要升级情况:没有旧的版本号
|
|
3645
|
+
await option!.conn!.execute(SyncMode.Async, 'INSERT INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option!.tableName, lastVersion]);
|
|
3646
|
+
}
|
|
3647
|
+
} else { // 表不存在
|
|
3648
|
+
// 创建表
|
|
3649
|
+
await option!.conn!.execute(SyncMode.Async, `
|
|
3650
|
+
CREATE TABLE IF NOT EXISTS ${tableES}(
|
|
3651
|
+
${Object.values(this[_fields]!).map(K => K[DBType.Sqlite]()).join(',')}
|
|
3652
|
+
${this[_ids] && this[_ids].length ? `, PRIMARY KEY (${this[_ids].map(i => this[_fields]![i]?.C2()).join(',')})` : ''}
|
|
3653
|
+
);
|
|
3654
|
+
`);
|
|
3655
|
+
if (this[_index] && this[_index].length) {
|
|
3656
|
+
for (const index of this[_index]) {
|
|
3657
|
+
await option!.conn!.execute(SyncMode.Async, `CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${Sqlstring.escapeId(option!.tableName)} ("${this[_fields]![index]?.C2()}");`);
|
|
3658
|
+
}
|
|
3659
|
+
}
|
|
3660
|
+
await option!.conn!.execute(SyncMode.Async, 'INSERT OR REPLACE INTO TABLE_VERSION (______tableName, ______version ) VALUES ( ?, ? )', [option!.tableName, lastVersion]);
|
|
3661
|
+
}
|
|
3662
|
+
resolve();
|
|
3663
|
+
} catch (error) {
|
|
3664
|
+
reject(error);
|
|
3665
|
+
}
|
|
3666
|
+
});
|
|
3667
|
+
}
|
|
3668
|
+
}
|
|
3669
|
+
|
|
3527
3670
|
/**
|
|
3528
3671
|
#创建表
|
|
3529
3672
|
** `tableName` 表名称
|
|
@@ -3569,16 +3712,16 @@ export class SqlService<T extends object> {
|
|
|
3569
3712
|
tableName = Sqlstring.escapeId(tableName ?? this[_tableName]);
|
|
3570
3713
|
switch (this[_dbType]) {
|
|
3571
3714
|
case DBType.Mysql: {
|
|
3572
|
-
let sql =
|
|
3715
|
+
let sql = formatDialect(`CREATE ${temp === true ? 'TEMPORARY' : ''} TABLE IF NOT EXISTS ${tableName}(
|
|
3573
3716
|
${columns.map(K => this[_fields]![K]![DBType.Mysql]()).join(',')}
|
|
3574
3717
|
${ids && ids.length ? `,PRIMARY KEY (${ids.map(i => this[_fields]![i]?.C2()).join(',')}) USING BTREE ` : ''}
|
|
3575
3718
|
${indexs && indexs.length ? `,${indexs.map(i => `KEY ${this[_fields]![i]?.C2()} (${this[_fields]![i]?.C2()})`).join(',')} ` : ''}
|
|
3576
|
-
) ENGINE=MEMORY
|
|
3719
|
+
) ENGINE=MEMORY;`, { dialect: this[_formatDialect]! });
|
|
3577
3720
|
sqls.push({ sql });
|
|
3578
3721
|
if (data && data.length > 0) {
|
|
3579
3722
|
const params: any[] = [];
|
|
3580
3723
|
let first = true;
|
|
3581
|
-
sql =
|
|
3724
|
+
sql = formatDialect(`INSERT INTO ${tableName} (${columns.map(c => this[_fields]![c]?.C2()).join(',')})
|
|
3582
3725
|
${(data).map(d => {
|
|
3583
3726
|
const r = `SELECT ${Object.entries(d).map(([K, V]) => {
|
|
3584
3727
|
params.push(V);
|
|
@@ -3586,28 +3729,28 @@ export class SqlService<T extends object> {
|
|
|
3586
3729
|
}).join(',')}`;
|
|
3587
3730
|
first = false;
|
|
3588
3731
|
return r;
|
|
3589
|
-
}).join(' UNION ALL ')}
|
|
3732
|
+
}).join(' UNION ALL ')}`, { dialect: this[_formatDialect]! });
|
|
3590
3733
|
sqls.push({ sql, params });
|
|
3591
3734
|
}
|
|
3592
3735
|
break;
|
|
3593
3736
|
}
|
|
3594
3737
|
case DBType.Sqlite:
|
|
3595
3738
|
case DBType.SqliteRemote: {
|
|
3596
|
-
let sql =
|
|
3739
|
+
let sql = formatDialect(`CREATE ${temp === true ? 'TEMPORARY' : ''} TABLE IF NOT EXISTS ${tableName}(
|
|
3597
3740
|
${columns.map(K => this[_fields]![K]![DBType.Sqlite]()).join(',')}
|
|
3598
3741
|
${ids && ids.length ? `,PRIMARY KEY (${ids.map(i => this[_fields]![i]?.C2()).join(',')}) ` : ''}
|
|
3599
|
-
)
|
|
3742
|
+
);`, { dialect: this[_formatDialect]! });
|
|
3600
3743
|
sqls.push({ sql });
|
|
3601
3744
|
if (indexs) {
|
|
3602
3745
|
for (const index of indexs) {
|
|
3603
|
-
sql =
|
|
3746
|
+
sql = formatDialect(`CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${tableName} (${this[_fields]![index]?.C2()});`, { dialect: this[_formatDialect]! });
|
|
3604
3747
|
sqls.push({ sql });
|
|
3605
3748
|
}
|
|
3606
3749
|
}
|
|
3607
3750
|
if (data && data.length > 0) {
|
|
3608
3751
|
const params: any[] = [];
|
|
3609
3752
|
let first = true;
|
|
3610
|
-
sql =
|
|
3753
|
+
sql = formatDialect(`INSERT INTO ${tableName} (${columns.map(c => this[_fields]![c]?.C2()).join(',')})
|
|
3611
3754
|
${(data).map(d => {
|
|
3612
3755
|
const r = `SELECT ${Object.entries(d).map(([K, V]) => {
|
|
3613
3756
|
params.push(V);
|
|
@@ -3615,7 +3758,7 @@ export class SqlService<T extends object> {
|
|
|
3615
3758
|
}).join(',')}`;
|
|
3616
3759
|
first = false;
|
|
3617
3760
|
return r;
|
|
3618
|
-
}).join(' UNION ALL ')}
|
|
3761
|
+
}).join(' UNION ALL ')}`, { dialect: this[_formatDialect]! });
|
|
3619
3762
|
sqls.push({ sql, params });
|
|
3620
3763
|
}
|
|
3621
3764
|
break;
|