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/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 { format } from 'sql-formatter';
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: any;
398
+ ctx?: any;
374
399
  isCount?: boolean;
400
+ isSum?: boolean;
375
401
  limitStart?: number;
376
402
  limitEnd?: number;
377
403
  orderBy?: string;
378
- [k: string]: any;
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(dbName: string, sql?: string, params?: any): | Promise<{ affectedRows: number; insertId: bigint; }>
509
- pluck<One_Row_Many_Column = any>(dbName: string, sql?: string, params?: any): Promise<One_Row_Many_Column | null>;
510
- get<One_Row_Many_Column = any>(dbName: string, sql?: string, params?: any): Promise<One_Row_Many_Column | null>;
511
- raw<Many_Row_One_Column = any>(dbName: string, sql?: string, params?: any): Promise<Many_Row_One_Column[]>;
512
- query<Many_Row_Many_Column = any>(dbName: string, sql?: string, params?: any): Promise<Many_Row_Many_Column[]>;
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 { affectedRows, insertId } = await this[_daoConnection].execute(this[_sqliteRemoteName], sql, params);
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 r = await this[_daoConnection].pluck(this[_sqliteRemoteName], sql, params);
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 r = await this[_daoConnection].get(this[_sqliteRemoteName], sql, params);
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 r = await this[_daoConnection].raw(this[_sqliteRemoteName], sql, params);
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 r = await this[_daoConnection].query(this[_sqliteRemoteName], sql, params);
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(new SqliteRemoteConnection(this[_daoDB], this[_sqliteRemoteName]));
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: any;
1313
+ ctx?: any;
1286
1314
  isCount?: boolean;
1287
1315
  isSum?: boolean;
1288
1316
  limitStart?: number;
1289
1317
  limitEnd?: number;
1290
1318
  orderBy?: string;
1291
- [k: string]: any;
1319
+ params?: any;
1292
1320
  }) => string
1293
1321
  )>;
1294
1322
  type _SqlModel = Record<string, string | (
1295
1323
  (options: {
1296
- ctx: any;
1324
+ ctx?: any;
1297
1325
  isCount?: boolean;
1298
1326
  isSum?: boolean;
1299
1327
  limitStart?: number;
1300
1328
  limitEnd?: number;
1301
1329
  orderBy?: string;
1302
- [k: string]: any;
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: any;
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
- const sql = mustache.render(_sql, buildParam, this.sqlFNMap);
1791
- return format(sql);
1843
+ return mustache.render(_sql, buildParam, this.sqlFNMap);
1792
1844
  } else if (typeof sqlSource === 'string') {
1793
- const sql = mustache.render(sqlSource, buildParam, this.sqlFNMap);
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
- console.log(_sql);
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 = __columns.filter((c: string) => __ids.includes(c) === false);
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] = config.dbType ?? DBType.Mysql;
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 = format(`INSERT INTO
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 = format(`
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 = format(`
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: format(`
2594
+ sql: formatDialect(`
2622
2595
  INSERT INTO
2623
2596
  ${tableTemp}
2624
2597
  (${columnNames})
2625
2598
  VALUES ${questMarks};
2626
- `), params
2599
+ `, { dialect: this[_formatDialect]! }), params
2627
2600
  });
2628
2601
  sqls.push({
2629
- sql: format(`INSERT INTO ${Sqlstring.escapeId(option.tableName)} (${columnNames})
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
- return await option?.dao?.transaction(SyncMode.Async, async () => {
2702
- const result = await excuteSplit<Partial<T>, bigint>(
2703
- ExcuteSplitMode.AsyncTrust,
2704
- datas,
2705
- async _data => {
2706
- const sqls = this._insert(_data, option);
2707
- let result = 0n;
2708
- for (const { sql, params } of sqls) {
2709
- const dd = await option?.conn!.execute(SyncMode.Async, sql, params);
2710
- if (dd.insertId) { result += dd.insertId; }
2711
- }
2712
- return result;
2713
- },
2714
- { everyLength: option?.every === true ? 1 : option?.maxDeal }
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 = format(`UPDATE ${tableName} SET ${iterare(this[_columnsNoId]!)
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: format(`
2913
+ sql: formatDialect(`
2943
2914
  UPDATE ${tableNameESC} SET ${this[_fields]![this[_stateFileName]]?.C2()} = ?
2944
2915
  WHERE ${whereSql};
2945
- `), params
2916
+ `, { dialect: this[_formatDialect]! }), params
2946
2917
  });
2947
2918
  } else {
2948
- sqls.push({ sql: format(`DELETE FROM ${tableNameESC} WHERE ${whereSql};`), params });
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: format(`UPDATE ${tableNameESC} a INNER JOIN ${tableTempESC} b ON ${delWhere.map(K => `a.${this[_fields]![K]?.C2()} = b.${this[_fields]![K]?.C2()}`).join(' AND ')}
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: format(`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 ')};`)
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: format(`UPDATE ${tableNameESC} SET ${this[_fields]![this[_stateFileName]]?.C2()} = ?
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: format(`DELETE FROM ${tableNameESC} WHERE (${columnNames}) IN (SELECT ${columnNames} FROM ${tableTempESC});`) });
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 = format(iterare(wheres).map(where => this[_transformer]!(where, option)).map(where => {
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: format(`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 ')};`) });
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?: 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>>;
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: number; pageNumber: number; limitSelf?: boolean; countSelf?: boolean; sumSelf?: boolean; orderBy?: string; hump?: boolean; mapper?: string | SqlMapper; mapperIfUndefined?: MapperIfUndefined; }): PageQuery<L> | Promise<PageQuery<L>> {
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 = format(`CREATE ${temp === true ? 'TEMPORARY' : ''} TABLE IF NOT EXISTS ${tableName}(
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 = format(`INSERT INTO ${tableName} (${columns.map(c => this[_fields]![c]?.C2()).join(',')})
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 = format(`CREATE ${temp === true ? 'TEMPORARY' : ''} TABLE IF NOT EXISTS ${tableName}(
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 = format(`CREATE INDEX ${Sqlstring.escapeId(`${index}_${Math.random()}`.replace(/\./, ''))} ON ${tableName} (${this[_fields]![index]?.C2()});`);
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 = format(`INSERT INTO ${tableName} (${columns.map(c => this[_fields]![c]?.C2()).join(',')})
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;