baja-lite 1.8.0 → 1.8.2

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/sql.js CHANGED
@@ -18,12 +18,12 @@ import pino from 'pino';
18
18
  import { formatDialect, mysql, postgresql, sqlite } from 'sql-formatter';
19
19
  import tslib from 'tslib';
20
20
  import { convert } from './convert-xml.js';
21
- import { Throw } from './error.js';
21
+ import { DatabaseError, Throw } from './error.js';
22
22
  import { excuteSplit, ExcuteSplitMode, sleep } from './fn.js';
23
23
  import { add, calc, ten2Any } from './math.js';
24
24
  import { C2P, C2P2, P2C } from './object.js';
25
25
  import { snowflake } from './snowflake.js';
26
- import { emptyString } from './string.js';
26
+ import { emptyString, replacePlaceholders } from './string.js';
27
27
  const iterate = ite.iterate;
28
28
  BigInt.prototype.toJSON = function () { return this.toString(); };
29
29
  const BIGINT_EXT_TYPE = 0;
@@ -80,6 +80,9 @@ export const _EventBus = Symbol('EventBus');
80
80
  export const _LoggerService = Symbol('LoggerService');
81
81
  export const _path = Symbol('path');
82
82
  export const _fs = Symbol('fs');
83
+ // 常量定义
84
+ const DEFAULT_KEEPALIVE_INTERVAL = 30000; // 30 秒
85
+ const DEFAULT_MAX_DEAL = 500; // 默认批量处理数量
83
86
  // export const logger = pino({
84
87
  // name: 'sql',
85
88
  // transport: {
@@ -210,7 +213,7 @@ export var ColumnMode;
210
213
  })(ColumnMode || (ColumnMode = {}));
211
214
  export const SqliteMemory = ':memory:';
212
215
  export const _defOption = {
213
- maxDeal: 500,
216
+ maxDeal: DEFAULT_MAX_DEAL,
214
217
  skipUndefined: true,
215
218
  skipNull: true,
216
219
  skipEmptyString: true
@@ -228,7 +231,7 @@ class MysqlConnection {
228
231
  }
229
232
  ;
230
233
  if (sync === SyncMode.Sync) {
231
- globalThis[_LoggerService].warn('MYSQL not suppouted sync mode');
234
+ globalThis[_LoggerService].warn('MYSQL not supported sync mode');
232
235
  return { affectedRows: 0, insertId: 0n };
233
236
  }
234
237
  ;
@@ -245,12 +248,9 @@ class MysqlConnection {
245
248
  resolve({ affectedRows: result.affectedRows, insertId: result.insertId });
246
249
  }
247
250
  catch (error) {
248
- globalThis[_LoggerService].error(`
249
- error: ${error},
250
- sql: ${sql},
251
- params: ${params}
252
- `);
253
- reject(error);
251
+ const dbError = DatabaseError.query('MySQL execute failed', sql, params, error);
252
+ globalThis[_LoggerService].error(dbError.getSafeMessage(), { cause: error });
253
+ reject(dbError);
254
254
  }
255
255
  });
256
256
  }
@@ -261,7 +261,7 @@ class MysqlConnection {
261
261
  }
262
262
  ;
263
263
  if (sync === SyncMode.Sync) {
264
- globalThis[_LoggerService].warn('MYSQL not suppouted sync mode');
264
+ globalThis[_LoggerService].warn('MYSQL not supported sync mode');
265
265
  return null;
266
266
  }
267
267
  ;
@@ -273,12 +273,11 @@ class MysqlConnection {
273
273
  const [result] = await this[_daoConnection].query(sql, params);
274
274
  if (result && result[0]) {
275
275
  const r = Object.values(result[0])[0];
276
- if (r === null)
277
- resolve(r);
278
- else
279
- resolve(r);
276
+ resolve(r === null ? null : r);
277
+ }
278
+ else {
279
+ resolve(null);
280
280
  }
281
- resolve(null);
282
281
  }
283
282
  catch (error) {
284
283
  globalThis[_LoggerService].error(`
@@ -297,7 +296,7 @@ class MysqlConnection {
297
296
  }
298
297
  ;
299
298
  if (sync === SyncMode.Sync) {
300
- globalThis[_LoggerService].warn('MYSQL not suppouted sync mode');
299
+ globalThis[_LoggerService].warn('MYSQL not supported sync mode');
301
300
  return null;
302
301
  }
303
302
  ;
@@ -331,7 +330,7 @@ class MysqlConnection {
331
330
  }
332
331
  ;
333
332
  if (sync === SyncMode.Sync) {
334
- globalThis[_LoggerService].warn('MYSQL not suppouted sync mode');
333
+ globalThis[_LoggerService].warn('MYSQL not supported sync mode');
335
334
  return [];
336
335
  }
337
336
  ;
@@ -365,7 +364,7 @@ class MysqlConnection {
365
364
  }
366
365
  ;
367
366
  if (sync === SyncMode.Sync) {
368
- globalThis[_LoggerService].warn('MYSQL not suppouted sync mode');
367
+ globalThis[_LoggerService].warn('MYSQL not supported sync mode');
369
368
  return [];
370
369
  }
371
370
  ;
@@ -404,15 +403,20 @@ class MysqlConnection {
404
403
  _b = _inTransaction;
405
404
  export class Mysql {
406
405
  constructor(pool) {
406
+ this.isClosing = false;
407
407
  this[_daoDB] = pool;
408
408
  this.keepAlive();
409
409
  }
410
410
  async keepAlive() {
411
+ if (this.isClosing)
412
+ return;
411
413
  let connection = null;
412
414
  try {
413
415
  connection = await this.createConnection(SyncMode.Async);
414
- const data = await connection?.query(SyncMode.Async, 'SELECT 1 FROM DUAL');
415
- globalThis[_LoggerService].debug?.('keepAlive->', data?.[0]?.[1]);
416
+ if (connection) {
417
+ const data = await connection.query(SyncMode.Async, 'SELECT 1 FROM DUAL');
418
+ globalThis[_LoggerService].debug?.('keepAlive->', data?.[0]?.[1]);
419
+ }
416
420
  }
417
421
  catch (error) {
418
422
  globalThis[_LoggerService].error('keepAlive error', error);
@@ -421,12 +425,14 @@ export class Mysql {
421
425
  if (connection) {
422
426
  await connection.release(SyncMode.Async);
423
427
  }
424
- setTimeout(() => this.keepAlive(), globalThis[_MysqlKeepAliveTime] ?? 30000);
428
+ if (!this.isClosing) {
429
+ this.keepAliveTimer = setTimeout(() => this.keepAlive(), globalThis[_MysqlKeepAliveTime] ?? DEFAULT_KEEPALIVE_INTERVAL);
430
+ }
425
431
  }
426
432
  }
427
433
  createConnection(sync) {
428
434
  if (sync === SyncMode.Sync) {
429
- globalThis[_LoggerService].error('MYSQL not suppouted sync mode');
435
+ globalThis[_LoggerService].error('MYSQL not supported sync mode');
430
436
  return null;
431
437
  }
432
438
  ;
@@ -437,13 +443,15 @@ export class Mysql {
437
443
  resolve(new MysqlConnection(connection));
438
444
  }
439
445
  catch (error) {
440
- reject(error);
446
+ const dbError = DatabaseError.connection('Failed to create MySQL connection', error);
447
+ globalThis[_LoggerService].error(dbError.getSafeMessage(), { cause: error });
448
+ reject(dbError);
441
449
  }
442
450
  });
443
451
  }
444
452
  transaction(sync, fn, conn) {
445
453
  if (sync === SyncMode.Sync) {
446
- globalThis[_LoggerService].warn('MYSQL not suppouted sync mode');
454
+ globalThis[_LoggerService].warn('MYSQL not supported sync mode');
447
455
  return null;
448
456
  }
449
457
  ;
@@ -466,18 +474,19 @@ export class Mysql {
466
474
  if (needCommit) {
467
475
  globalThis[_LoggerService].debug?.('commit begin!');
468
476
  await conn[_daoConnection].commit();
469
- conn[_inTransaction] = false;
470
477
  globalThis[_LoggerService].debug?.('commit end!');
471
478
  }
472
479
  resolve(result);
473
480
  }
474
481
  catch (error) {
475
- globalThis[_LoggerService].debug?.('rollback begin!');
476
- await conn[_daoConnection].rollback();
477
- globalThis[_LoggerService].debug?.('rollback end!');
478
- conn[_inTransaction] = false;
479
- globalThis[_LoggerService].error(error);
480
- reject(error);
482
+ if (needCommit) {
483
+ globalThis[_LoggerService].debug?.('rollback begin!');
484
+ await conn[_daoConnection].rollback();
485
+ globalThis[_LoggerService].debug?.('rollback end!');
486
+ }
487
+ const dbError = error instanceof DatabaseError ? error : DatabaseError.transaction('MySQL transaction failed', error);
488
+ globalThis[_LoggerService].error(dbError.getSafeMessage(), { cause: error });
489
+ reject(dbError);
481
490
  }
482
491
  finally {
483
492
  try {
@@ -491,15 +500,18 @@ export class Mysql {
491
500
  }
492
501
  }
493
502
  catch (error) {
503
+ // 释放连接失败通常不影响业务逻辑,记录日志即可
504
+ globalThis[_LoggerService].warn?.('Failed to release connection in finally block', error);
494
505
  }
495
506
  }
496
507
  });
497
508
  }
498
509
  close(sync) {
499
- if (sync === SyncMode.Sync) {
500
- this[_daoDB]?.destroy();
510
+ this.isClosing = true;
511
+ if (this.keepAliveTimer) {
512
+ clearTimeout(this.keepAliveTimer);
501
513
  }
502
- ;
514
+ return this[_daoDB]?.destroy();
503
515
  }
504
516
  backup(sync, name) {
505
517
  }
@@ -520,7 +532,7 @@ class PostgresqlConnection {
520
532
  }
521
533
  ;
522
534
  if (sync === SyncMode.Sync) {
523
- globalThis[_LoggerService].warn('Postgresql not suppouted sync mode');
535
+ globalThis[_LoggerService].warn('Postgresql not supported sync mode');
524
536
  return { affectedRows: 0, insertId: 0n };
525
537
  }
526
538
  ;
@@ -529,16 +541,15 @@ class PostgresqlConnection {
529
541
  }
530
542
  return new Promise(async (resolve, reject) => {
531
543
  try {
532
- let index = 1;
533
544
  const { rowCount } = await this[_daoConnection].query({
534
- text: sql.replace(/\?/g, () => `$${index++}`),
545
+ text: replacePlaceholders(sql),
535
546
  values: params
536
547
  });
537
548
  const result = rowCount;
538
549
  if (globalThis[_GlobalSqlOption].log === 'trace') {
539
550
  globalThis[_LoggerService].verbose?.(result);
540
551
  }
541
- resolve({ affectedRows: result.affectedRows, insertId: result.insertId });
552
+ resolve({ affectedRows: rowCount || 0, insertId: 0n });
542
553
  }
543
554
  catch (error) {
544
555
  globalThis[_LoggerService].error(`
@@ -557,7 +568,7 @@ class PostgresqlConnection {
557
568
  }
558
569
  ;
559
570
  if (sync === SyncMode.Sync) {
560
- globalThis[_LoggerService].warn('Postgresql not suppouted sync mode');
571
+ globalThis[_LoggerService].warn('Postgresql not supported sync mode');
561
572
  return null;
562
573
  }
563
574
  ;
@@ -566,9 +577,8 @@ class PostgresqlConnection {
566
577
  }
567
578
  return new Promise(async (resolve, reject) => {
568
579
  try {
569
- let index = 1;
570
580
  const { rows } = await this[_daoConnection].query({
571
- text: sql.replace(/\?/g, () => `$${index++}`),
581
+ text: replacePlaceholders(sql),
572
582
  values: params
573
583
  });
574
584
  if (rows && rows[0]) {
@@ -597,7 +607,7 @@ class PostgresqlConnection {
597
607
  }
598
608
  ;
599
609
  if (sync === SyncMode.Sync) {
600
- globalThis[_LoggerService].warn('Postgresql not suppouted sync mode');
610
+ globalThis[_LoggerService].warn('Postgresql not supported sync mode');
601
611
  return null;
602
612
  }
603
613
  ;
@@ -606,9 +616,8 @@ class PostgresqlConnection {
606
616
  }
607
617
  return new Promise(async (resolve, reject) => {
608
618
  try {
609
- let index = 1;
610
619
  const { rows } = await this[_daoConnection].query({
611
- text: sql.replace(/\?/g, () => `$${index++}`),
620
+ text: replacePlaceholders(sql),
612
621
  values: params
613
622
  });
614
623
  if (globalThis[_GlobalSqlOption].log === 'trace') {
@@ -635,7 +644,7 @@ class PostgresqlConnection {
635
644
  }
636
645
  ;
637
646
  if (sync === SyncMode.Sync) {
638
- globalThis[_LoggerService].warn('Postgresql not suppouted sync mode');
647
+ globalThis[_LoggerService].warn('Postgresql not supported sync mode');
639
648
  return [];
640
649
  }
641
650
  ;
@@ -644,9 +653,8 @@ class PostgresqlConnection {
644
653
  }
645
654
  return new Promise(async (resolve, reject) => {
646
655
  try {
647
- let index = 1;
648
656
  const { rows } = await this[_daoConnection].query({
649
- text: sql.replace(/\?/g, () => `$${index++}`),
657
+ text: replacePlaceholders(sql),
650
658
  values: params
651
659
  });
652
660
  if (globalThis[_GlobalSqlOption].log === 'trace') {
@@ -673,7 +681,7 @@ class PostgresqlConnection {
673
681
  }
674
682
  ;
675
683
  if (sync === SyncMode.Sync) {
676
- globalThis[_LoggerService].warn('Postgresql not suppouted sync mode');
684
+ globalThis[_LoggerService].warn('Postgresql not supported sync mode');
677
685
  return [];
678
686
  }
679
687
  ;
@@ -682,9 +690,8 @@ class PostgresqlConnection {
682
690
  }
683
691
  return new Promise(async (resolve, reject) => {
684
692
  try {
685
- let index = 1;
686
693
  const { rows } = await this[_daoConnection].query({
687
- text: sql.replace(/\?/g, () => `$${index++}`),
694
+ text: replacePlaceholders(sql),
688
695
  values: params
689
696
  });
690
697
  if (globalThis[_GlobalSqlOption].log === 'trace') {
@@ -716,11 +723,36 @@ class PostgresqlConnection {
716
723
  _c = _inTransaction;
717
724
  export class Postgresql {
718
725
  constructor(pool) {
726
+ this.isClosing = false;
719
727
  this[_daoDB] = pool;
728
+ this.keepAlive();
729
+ }
730
+ async keepAlive() {
731
+ if (this.isClosing)
732
+ return;
733
+ let connection = null;
734
+ try {
735
+ connection = await this.createConnection(SyncMode.Async);
736
+ if (connection) {
737
+ const data = await connection.query(SyncMode.Async, 'SELECT 1 FROM DUAL');
738
+ globalThis[_LoggerService].debug?.('keepAlive->', data?.[0]?.[1]);
739
+ }
740
+ }
741
+ catch (error) {
742
+ globalThis[_LoggerService].error('keepAlive error', error);
743
+ }
744
+ finally {
745
+ if (connection) {
746
+ await connection.release(SyncMode.Async);
747
+ }
748
+ if (!this.isClosing) {
749
+ this.keepAliveTimer = setTimeout(() => this.keepAlive(), globalThis[_MysqlKeepAliveTime] ?? DEFAULT_KEEPALIVE_INTERVAL);
750
+ }
751
+ }
720
752
  }
721
753
  createConnection(sync) {
722
754
  if (sync === SyncMode.Sync) {
723
- globalThis[_LoggerService].error('Postgresql not suppouted sync mode');
755
+ globalThis[_LoggerService].error('Postgresql not supported sync mode');
724
756
  return null;
725
757
  }
726
758
  ;
@@ -737,7 +769,7 @@ export class Postgresql {
737
769
  }
738
770
  transaction(sync, fn, conn) {
739
771
  if (sync === SyncMode.Sync) {
740
- globalThis[_LoggerService].warn('Postgresql not suppouted sync mode');
772
+ globalThis[_LoggerService].warn('Postgresql not supported sync mode');
741
773
  return null;
742
774
  }
743
775
  ;
@@ -760,18 +792,19 @@ export class Postgresql {
760
792
  if (needCommit) {
761
793
  globalThis[_LoggerService].debug?.('commit begin!');
762
794
  await conn[_daoConnection].query('COMMIT');
763
- conn[_inTransaction] = false;
764
795
  globalThis[_LoggerService].debug?.('commit end!');
765
796
  }
766
797
  resolve(result);
767
798
  }
768
799
  catch (error) {
769
- globalThis[_LoggerService].debug?.('rollback begin!');
770
- await conn[_daoConnection].query('ROLLBACK');
771
- globalThis[_LoggerService].debug?.('rollback end!');
772
- conn[_inTransaction] = false;
773
- globalThis[_LoggerService].error(error);
774
- reject(error);
800
+ if (needCommit) {
801
+ globalThis[_LoggerService].debug?.('rollback begin!');
802
+ await conn[_daoConnection].query('ROLLBACK');
803
+ globalThis[_LoggerService].debug?.('rollback end!');
804
+ }
805
+ const dbError = error instanceof DatabaseError ? error : DatabaseError.transaction('PostgreSQL transaction failed', error);
806
+ globalThis[_LoggerService].error(dbError.getSafeMessage(), { cause: error });
807
+ reject(dbError);
775
808
  }
776
809
  finally {
777
810
  try {
@@ -785,15 +818,18 @@ export class Postgresql {
785
818
  }
786
819
  }
787
820
  catch (error) {
821
+ // 释放连接失败通常不影响业务逻辑,记录日志即可
822
+ globalThis[_LoggerService].warn?.('Failed to release connection in finally block', error);
788
823
  }
789
824
  }
790
825
  });
791
826
  }
792
827
  close(sync) {
793
- if (sync === SyncMode.Sync) {
794
- this[_daoDB]?.end();
828
+ this.isClosing = true;
829
+ if (this.keepAliveTimer) {
830
+ clearTimeout(this.keepAliveTimer);
795
831
  }
796
- ;
832
+ this[_daoDB]?.end();
797
833
  }
798
834
  backup(sync, name) {
799
835
  }
@@ -815,7 +851,7 @@ class SqliteConnection {
815
851
  }
816
852
  ;
817
853
  if (sync === SyncMode.Async) {
818
- globalThis[_LoggerService].warn(`SQLITE not suppoted async mode`);
854
+ globalThis[_LoggerService].warn(`SQLITE not supported async mode`);
819
855
  return { affectedRows: 0, insertId: 0n };
820
856
  }
821
857
  ;
@@ -846,7 +882,7 @@ class SqliteConnection {
846
882
  }
847
883
  ;
848
884
  if (sync === SyncMode.Async) {
849
- globalThis[_LoggerService].warn(`SQLITE not suppoted async mode`);
885
+ globalThis[_LoggerService].warn(`SQLITE not supported async mode`);
850
886
  return null;
851
887
  }
852
888
  ;
@@ -897,7 +933,7 @@ class SqliteConnection {
897
933
  }
898
934
  ;
899
935
  if (sync === SyncMode.Async) {
900
- globalThis[_LoggerService].warn(`SQLITE not suppoted async mode`);
936
+ globalThis[_LoggerService].warn(`SQLITE not supported async mode`);
901
937
  return [];
902
938
  }
903
939
  ;
@@ -923,7 +959,7 @@ class SqliteConnection {
923
959
  }
924
960
  ;
925
961
  if (sync === SyncMode.Async) {
926
- globalThis[_LoggerService].warn(`SQLITE not suppoted async mode`);
962
+ globalThis[_LoggerService].warn(`SQLITE not supported async mode`);
927
963
  return [];
928
964
  }
929
965
  ;
@@ -961,7 +997,13 @@ export class Sqlite {
961
997
  `);
962
998
  this[_daoDB].function('UUID_SHORT', { deterministic: false }, () => snowflake.generate());
963
999
  this[_daoDB].function('UUID', { deterministic: false }, () => snowflake.generate());
964
- this[_daoDB].function('TIME_TO_SEC', { deterministic: true }, (time) => time.split(':').map((v, i) => parseInt(v) * (i === 0 ? 360 : i === 1 ? 60 : 0)).reduce((a, b) => a + b, 0));
1000
+ this[_daoDB].function('TIME_TO_SEC', { deterministic: true }, (time) => {
1001
+ const parts = time.split(':');
1002
+ const hours = parseInt(parts[0] || '0');
1003
+ const minutes = parseInt(parts[1] || '0');
1004
+ const seconds = parseInt(parts[2] || '0');
1005
+ return hours * 3600 + minutes * 60 + seconds;
1006
+ });
965
1007
  this[_daoDB].function('IF', { deterministic: true }, (condition, v1, v2) => condition ? v1 : v2);
966
1008
  this[_daoDB].function('RIGHT', { deterministic: true }, (src, p) => src.slice(p * -1));
967
1009
  this[_daoDB].function('LEFT', { deterministic: true }, (str, len) => str?.substring(0, len) || null);
@@ -984,7 +1026,7 @@ export class Sqlite {
984
1026
  }
985
1027
  createConnection(sync) {
986
1028
  if (sync === SyncMode.Async) {
987
- globalThis[_LoggerService].error(`SQLITE not suppoted async mode`);
1029
+ globalThis[_LoggerService].error(`SQLITE not supported async mode`);
988
1030
  return null;
989
1031
  }
990
1032
  ;
@@ -992,7 +1034,7 @@ export class Sqlite {
992
1034
  }
993
1035
  transaction(sync, fn, conn) {
994
1036
  if (sync === SyncMode.Async) {
995
- globalThis[_LoggerService].warn(`SQLITE not suppoted async mode`);
1037
+ globalThis[_LoggerService].warn(`SQLITE not supported async mode`);
996
1038
  return null;
997
1039
  }
998
1040
  ;
@@ -1042,7 +1084,7 @@ export class SqliteRemoteConnection {
1042
1084
  }
1043
1085
  ;
1044
1086
  if (sync === SyncMode.Sync) {
1045
- globalThis[_LoggerService].warn('SqliteRemote not suppouted sync mode');
1087
+ globalThis[_LoggerService].warn('SqliteRemote not supported sync mode');
1046
1088
  return { affectedRows: 0, insertId: 0n };
1047
1089
  }
1048
1090
  ;
@@ -1072,7 +1114,7 @@ export class SqliteRemoteConnection {
1072
1114
  }
1073
1115
  ;
1074
1116
  if (sync === SyncMode.Sync) {
1075
- globalThis[_LoggerService].warn('SqliteRemote not suppouted sync mode');
1117
+ globalThis[_LoggerService].warn('SqliteRemote not supported sync mode');
1076
1118
  return null;
1077
1119
  }
1078
1120
  ;
@@ -1102,7 +1144,7 @@ export class SqliteRemoteConnection {
1102
1144
  }
1103
1145
  ;
1104
1146
  if (sync === SyncMode.Sync) {
1105
- globalThis[_LoggerService].warn('SqliteRemote not suppouted sync mode');
1147
+ globalThis[_LoggerService].warn('SqliteRemote not supported sync mode');
1106
1148
  return null;
1107
1149
  }
1108
1150
  ;
@@ -1132,7 +1174,7 @@ export class SqliteRemoteConnection {
1132
1174
  }
1133
1175
  ;
1134
1176
  if (sync === SyncMode.Sync) {
1135
- globalThis[_LoggerService].warn('SqliteRemote not suppouted sync mode');
1177
+ globalThis[_LoggerService].warn('SqliteRemote not supported sync mode');
1136
1178
  return [];
1137
1179
  }
1138
1180
  ;
@@ -1162,7 +1204,7 @@ export class SqliteRemoteConnection {
1162
1204
  }
1163
1205
  ;
1164
1206
  if (sync === SyncMode.Sync) {
1165
- globalThis[_LoggerService].warn('SqliteRemote not suppouted sync mode');
1207
+ globalThis[_LoggerService].warn('SqliteRemote not supported sync mode');
1166
1208
  return [];
1167
1209
  }
1168
1210
  ;
@@ -1196,7 +1238,7 @@ export class SqliteRemote {
1196
1238
  }
1197
1239
  createConnection(sync) {
1198
1240
  if (sync === SyncMode.Sync) {
1199
- globalThis[_LoggerService].error('SQLITEREMOTE not suppouted sync mode');
1241
+ globalThis[_LoggerService].error('SQLITEREMOTE not supported sync mode');
1200
1242
  return null;
1201
1243
  }
1202
1244
  ;
@@ -1213,7 +1255,7 @@ export class SqliteRemote {
1213
1255
  });
1214
1256
  }
1215
1257
  transaction(sync, fn, conn) {
1216
- globalThis[_LoggerService].warn(`SQLITEREMOTE not suppoted transaction`);
1258
+ globalThis[_LoggerService].warn(`SQLITEREMOTE not supported transaction`);
1217
1259
  return null;
1218
1260
  }
1219
1261
  close(sync) {
@@ -1832,7 +1874,11 @@ function P(skipConn = false) {
1832
1874
  return result;
1833
1875
  }
1834
1876
  catch (error) {
1835
- console.error(`${option.sqlId ?? option.tableName} service ${propertyKey} have an error:${error}, it's argumens: ${JSON.stringify(args.filter(i => typeof i !== 'object' || (typeof i === 'object' && !i.insert)))}`);
1877
+ let args = '';
1878
+ if (args.length > 0 && args[0].params) {
1879
+ args = JSON.stringify(args[0].params);
1880
+ }
1881
+ console.error(`${option.sqlId ?? option.tableName} service ${propertyKey} have an error:${error}, it's argumens: ${args}`);
1836
1882
  throw error;
1837
1883
  }
1838
1884
  finally {
package/string.d.ts CHANGED
@@ -18,7 +18,10 @@ export declare const emptyString: (source: any, skipEmptyString?: boolean) => bo
18
18
  */
19
19
  export declare const notEmptyString: (source: any, skipEmptyString?: boolean) => boolean;
20
20
  /**
21
- * 安全字符串处理(移除单引号,防止简单 SQL 注入)
21
+ * 安全字符串处理(移除单引号)
22
+ * @deprecated 不推荐用于 SQL 注入防护,请使用参数化查询
23
+ * @param source 源字符串
24
+ * @returns 移除单引号后的字符串
22
25
  */
23
26
  export declare const safeString: (source?: string) => string;
24
27
  /**
@@ -42,3 +45,5 @@ export declare const buildWxStr: (data: {
42
45
  * 将字符串中的中文标点符号统一替换为对应的英文标点
43
46
  */
44
47
  export declare const replaceChineseCode: (str: string) => string;
48
+ /** 更安全的sql 参数占位符替换 */
49
+ export declare function replacePlaceholders(sql: string): string;
package/string.js CHANGED
@@ -30,7 +30,10 @@ export const notEmptyString = (source, skipEmptyString = true) => {
30
30
  return emptyString(source, skipEmptyString) === false;
31
31
  };
32
32
  /**
33
- * 安全字符串处理(移除单引号,防止简单 SQL 注入)
33
+ * 安全字符串处理(移除单引号)
34
+ * @deprecated 不推荐用于 SQL 注入防护,请使用参数化查询
35
+ * @param source 源字符串
36
+ * @returns 移除单引号后的字符串
34
37
  */
35
38
  export const safeString = (source) => {
36
39
  if (source) {
@@ -130,3 +133,22 @@ const table = {
130
133
  export const replaceChineseCode = (str) => {
131
134
  return str.replace(chinese, (a) => table[a] || '');
132
135
  };
136
+ /** 更安全的sql 参数占位符替换 */
137
+ export function replacePlaceholders(sql) {
138
+ let index = 1;
139
+ let inString = false;
140
+ let result = '';
141
+ for (let i = 0; i < sql.length; i++) {
142
+ const char = sql[i];
143
+ if (char === "'" && sql[i - 1] !== '\\') {
144
+ inString = !inString;
145
+ }
146
+ if (char === '?' && !inString) {
147
+ result += `$${index++}`;
148
+ }
149
+ else {
150
+ result += char;
151
+ }
152
+ }
153
+ return result;
154
+ }