mm_sqlite 1.3.3 → 1.3.4

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/index.js CHANGED
@@ -14,6 +14,7 @@ class SQLite extends Base {
14
14
  * 默认配置
15
15
  */
16
16
  static config = {
17
+ name: 'default',
17
18
  dir: './db/'.fullname(),
18
19
  user: 'root',
19
20
  password: '',
@@ -44,10 +45,7 @@ class SQLite extends Base {
44
45
  * @param {object} config - 配置对象
45
46
  */
46
47
  constructor(config) {
47
- const merged_cfg = { ...SQLite.config, ...config || {}};
48
- super(merged_cfg);
49
-
50
- this.config = merged_cfg;
48
+ super(config);
51
49
  this._connection = null;
52
50
  this._pool = null;
53
51
  this._status = 'closed';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_sqlite",
3
- "version": "1.3.3",
3
+ "version": "1.3.4",
4
4
  "description": "高性能SQLite数据库操作模块,提供与mm_mysql完全兼容的API接口,支持异步操作、事务处理和批量操作",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/sql.js CHANGED
@@ -196,10 +196,10 @@ Sql.prototype.toQuery = function (where, sort, view) {
196
196
  if (!view) {
197
197
  view = '*';
198
198
  }
199
-
199
+
200
200
  // 使用直接拼接的方式,避免模板替换错误
201
201
  var sql = `SELECT ${view} FROM \`${this.table}\``;
202
-
202
+
203
203
  if (where) {
204
204
  sql += ' WHERE ' + where;
205
205
  }
@@ -345,7 +345,7 @@ Sql.prototype.groupMathSql = async function (where, groupby, view, sort, method)
345
345
  }
346
346
  } else {
347
347
  viewStr = ',' + method.toUpperCase() + '(' + escapeId(view) + ') ' + method.toLowerCase() + '_' +
348
- view.replace(/`/g, '');
348
+ view.replace(/`/g, '');
349
349
  }
350
350
  var sql = 'SELECT ' + (groupby ? escapeId(groupby) : '') + viewStr + ' FROM `' + this.table + '`';
351
351
  if (where) {
@@ -463,11 +463,11 @@ Sql.prototype.sum = async function (field, query) {
463
463
  if (!field || typeof field !== 'string') {
464
464
  throw new TypeError('字段名必须为字符串');
465
465
  }
466
-
466
+
467
467
  if (!this.table) {
468
468
  throw new TypeError('表名未设置');
469
469
  }
470
-
470
+
471
471
  const result = await this.groupSum(query, '', field, '');
472
472
  const fieldKey = 'sum_' + field.replace(/`/g, '');
473
473
  return result && result.length > 0 ? Number(result[0][fieldKey] || result[0].sum_age) : 0;
@@ -483,11 +483,11 @@ Sql.prototype.max = async function (field, query) {
483
483
  if (!field || typeof field !== 'string') {
484
484
  throw new TypeError('字段名必须为字符串');
485
485
  }
486
-
486
+
487
487
  if (!this.table) {
488
488
  throw new TypeError('表名未设置');
489
489
  }
490
-
490
+
491
491
  const result = await this.groupMath(query, '', field, '', 'MAX');
492
492
  const fieldKey = 'max_' + field.replace(/`/g, '');
493
493
  return result && result.length > 0 ? Number(result[0][fieldKey] || result[0].max_age) : 0;
@@ -503,11 +503,11 @@ Sql.prototype.min = async function (field, query) {
503
503
  if (!field || typeof field !== 'string') {
504
504
  throw new TypeError('字段名必须为字符串');
505
505
  }
506
-
506
+
507
507
  if (!this.table) {
508
508
  throw new TypeError('表名未设置');
509
509
  }
510
-
510
+
511
511
  const result = await this.groupMath(query, '', field, '', 'MIN');
512
512
  const fieldKey = 'min_' + field.replace(/`/g, '');
513
513
  return result && result.length > 0 ? Number(result[0][fieldKey] || result[0].min_age) : 0;
@@ -523,11 +523,11 @@ Sql.prototype.avg = async function (field, query) {
523
523
  if (!field || typeof field !== 'string') {
524
524
  throw new TypeError('字段名必须为字符串');
525
525
  }
526
-
526
+
527
527
  if (!this.table) {
528
528
  throw new TypeError('表名未设置');
529
529
  }
530
-
530
+
531
531
  const result = await this.groupMath(query, '', field, '', 'AVG');
532
532
  const fieldKey = 'avg_' + field.replace(/`/g, '');
533
533
  return result && result.length > 0 ? Number(result[0][fieldKey] || result[0].avg_age) : 0;
@@ -544,7 +544,7 @@ Sql.prototype.toStr = function (...args) {
544
544
  if (args.length === 0) {
545
545
  return '';
546
546
  }
547
-
547
+
548
548
  // 将所有参数转换为字符串并用空格连接
549
549
  return args.map(arg => String(arg)).join(' ');
550
550
  };
@@ -555,30 +555,30 @@ Sql.prototype.toStr = function (...args) {
555
555
  * @param {string} file 备份文件路径
556
556
  * @returns {Promise<boolean>} 备份是否成功
557
557
  */
558
- Sql.prototype.backup = async function(file) {
558
+ Sql.prototype.backup = async function (file) {
559
559
  if (!file || typeof file !== 'string') {
560
560
  throw new TypeError('文件路径必须为字符串');
561
561
  }
562
-
562
+
563
563
  if (!this.table) {
564
564
  throw new TypeError('表名未设置');
565
565
  }
566
-
566
+
567
567
  try {
568
568
  // 获取所有数据
569
569
  const data = await this.getSql('', '', '*');
570
-
570
+
571
571
  if (!data || !Array.isArray(data)) {
572
572
  throw new Error('获取数据失败');
573
573
  }
574
574
 
575
575
  // 构建 SQL 语句
576
576
  let sqlContent = '';
577
-
577
+
578
578
  // 添加表结构(简化版,实际应用中可能需要更复杂的表结构导出)
579
579
  sqlContent += `-- 备份表: ${this.table}\n`;
580
580
  sqlContent += `-- 备份时间: ${new Date().toISOString()}\n\n`;
581
-
581
+
582
582
  // 添加数据插入语句
583
583
  for (const row of data) {
584
584
  const keys = Object.keys(row).map(key => this.escapeId(key)).join(', ');
@@ -589,15 +589,15 @@ Sql.prototype.backup = async function(file) {
589
589
  // 写入文件(这里需要文件系统模块,实际使用时需要引入 fs)
590
590
  const fs = require('fs');
591
591
  const path = require('path');
592
-
592
+
593
593
  // 确保目录存在
594
594
  const dir = path.dirname(file);
595
595
  if (!fs.existsSync(dir)) {
596
596
  fs.mkdirSync(dir, { recursive: true });
597
597
  }
598
-
598
+
599
599
  fs.writeFileSync(file, sqlContent, 'utf8');
600
-
600
+
601
601
  return true;
602
602
  } catch (err) {
603
603
  this.error = err.message;
@@ -611,33 +611,33 @@ Sql.prototype.backup = async function(file) {
611
611
  * @param {string} file 恢复文件路径
612
612
  * @returns {Promise<boolean>} 恢复是否成功
613
613
  */
614
- Sql.prototype.restore = async function(file) {
614
+ Sql.prototype.restore = async function (file) {
615
615
  if (!file || typeof file !== 'string') {
616
616
  throw new TypeError('文件路径必须为字符串');
617
617
  }
618
-
618
+
619
619
  if (!this.table) {
620
620
  throw new TypeError('表名未设置');
621
621
  }
622
-
622
+
623
623
  try {
624
624
  const fs = require('fs');
625
-
625
+
626
626
  // 检查文件是否存在
627
627
  if (!fs.existsSync(file)) {
628
628
  throw new Error('备份文件不存在');
629
629
  }
630
-
630
+
631
631
  // 读取文件内容
632
632
  const sqlContent = fs.readFileSync(file, 'utf8');
633
-
633
+
634
634
  if (!sqlContent) {
635
635
  throw new Error('备份文件为空');
636
636
  }
637
-
637
+
638
638
  // 解析 SQL 语句(按分号分割,但需要处理字符串中的分号)
639
639
  const statements = this._parseSqlStatements(sqlContent);
640
-
640
+
641
641
  // 执行所有 SQL 语句
642
642
  for (const statement of statements) {
643
643
  if (statement.trim()) {
@@ -647,7 +647,7 @@ Sql.prototype.restore = async function(file) {
647
647
  }
648
648
  }
649
649
  }
650
-
650
+
651
651
  return true;
652
652
  } catch (err) {
653
653
  this.error = err.message;
@@ -662,22 +662,22 @@ Sql.prototype.restore = async function(file) {
662
662
  * @returns {string[]} SQL 语句数组
663
663
  * @private
664
664
  */
665
- Sql.prototype._parseSqlStatements = function(sql) {
665
+ Sql.prototype._parseSqlStatements = function (sql) {
666
666
  const statements = [];
667
667
  let currentStatement = '';
668
668
  let inString = false;
669
669
  let stringChar = '';
670
-
670
+
671
671
  for (let i = 0; i < sql.length; i++) {
672
672
  const char = sql[i];
673
-
673
+
674
674
  if (char === "'" || char === '"') {
675
675
  if (!inString) {
676
676
  inString = true;
677
677
  stringChar = char;
678
678
  } else if (char === stringChar) {
679
679
  // 检查是否是转义字符
680
- if (i > 0 && sql[i-1] === '\\') {
680
+ if (i > 0 && sql[i - 1] === '\\') {
681
681
  // 转义字符,继续字符串
682
682
  } else {
683
683
  inString = false;
@@ -685,7 +685,7 @@ Sql.prototype._parseSqlStatements = function(sql) {
685
685
  }
686
686
  }
687
687
  }
688
-
688
+
689
689
  if (!inString && char === ';') {
690
690
  statements.push(currentStatement.trim());
691
691
  currentStatement = '';
@@ -693,12 +693,12 @@ Sql.prototype._parseSqlStatements = function(sql) {
693
693
  currentStatement += char;
694
694
  }
695
695
  }
696
-
696
+
697
697
  // 添加最后一个语句(如果没有分号结尾)
698
698
  if (currentStatement.trim()) {
699
699
  statements.push(currentStatement.trim());
700
700
  }
701
-
701
+
702
702
  return statements.filter(stmt => stmt.length > 0);
703
703
  };
704
704
 
@@ -717,9 +717,6 @@ Sql.prototype.toWhere = function (obj, like) {
717
717
  if (like) {
718
718
  for (var k in obj) {
719
719
  var val = obj[k];
720
- if (val && typeof (val) === 'string') {
721
- val = val.trim("'");
722
- }
723
720
  val = escape(val);
724
721
  if (k.endsWith('_min')) {
725
722
  where += ' and ' + escapeId(k.replace('_min', '')) + ' >= ' + val;
@@ -729,7 +726,7 @@ Sql.prototype.toWhere = function (obj, like) {
729
726
  where += ' and ' + escapeId(k.replace('_not', '')) + ' != ' + val;
730
727
  } else if (k.endsWith('_has')) {
731
728
  var vals = val.trim("'").split(',').map((o) => {
732
- return "'" + o + "'";
729
+ return escape(o);
733
730
  });
734
731
  where += ' and ' + escapeId(k.replace('_has', '')) + ' in (' + vals.join(',') + ')';
735
732
  } else if (k.endsWith('_like')) {
@@ -743,9 +740,6 @@ Sql.prototype.toWhere = function (obj, like) {
743
740
  } else {
744
741
  for (var k in obj) {
745
742
  var val = obj[k];
746
- if (val && typeof (val) === 'string') {
747
- val = val.trim("'");
748
- }
749
743
  val = escape(val);
750
744
  if (k.endsWith('_min')) {
751
745
  where += ' and ' + escapeId(k.replace('_min', '')) + ' >= ' + val;
@@ -755,7 +749,7 @@ Sql.prototype.toWhere = function (obj, like) {
755
749
  where += ' and ' + escapeId(k.replace('_not', '')) + ' != ' + val;
756
750
  } else if (k.endsWith('_has')) {
757
751
  var vals = val.trim("'").split(',').map((o) => {
758
- return "'" + o + "'";
752
+ return escape(o);
759
753
  });
760
754
  where += ' and ' + escapeId(k.replace('_has', '')) + ' in (' + vals.join(',') + ')';
761
755
  } else {
@@ -774,14 +768,8 @@ Sql.prototype.toWhere = function (obj, like) {
774
768
  Sql.prototype.toSet = function (obj) {
775
769
  var set = '';
776
770
  for (var k in obj) {
777
- if (!Object.prototype.hasOwnProperty.call(obj, k)) continue;
778
-
779
771
  var val = obj[k];
780
772
  if (val === undefined || val === null) continue;
781
-
782
- if (typeof val === 'string') {
783
- val = val.trim("'");
784
- }
785
773
  val = escape(val);
786
774
 
787
775
  if (k.endsWith('_add')) {
@@ -811,13 +799,8 @@ Sql.prototype.toAddSql = function (item) {
811
799
  let value = '';
812
800
 
813
801
  for (const k in item) {
814
- if (!Object.prototype.hasOwnProperty.call(item, k)) continue;
815
-
816
802
  key += ',' + escapeId(k);
817
803
  let val = item[k];
818
- if (typeof val === 'string') {
819
- val = val.trim("'");
820
- }
821
804
  value += ',' + escape(val);
822
805
  }
823
806
 
@@ -838,10 +821,10 @@ Sql.prototype.toDelSql = function (query, like) {
838
821
  throw new Error('表名未设置');
839
822
  }
840
823
  const where = this.toWhere(query, like);
841
-
824
+
842
825
  // 使用直接拼接的方式,避免模板替换错误
843
826
  const sql = `DELETE FROM \`${this.table}\` WHERE ${where};`;
844
-
827
+
845
828
  return sql;
846
829
  };
847
830
 
@@ -858,10 +841,10 @@ Sql.prototype.toSetSql = function (query, item, like) {
858
841
  }
859
842
  const where = this.toWhere(query, like);
860
843
  const set = this.toSet(item);
861
-
844
+
862
845
  // 使用直接拼接的方式,避免模板替换错误
863
846
  const sql = `UPDATE \`${this.table}\` SET ${set} WHERE ${where};`;
864
-
847
+
865
848
  return sql;
866
849
  };
867
850
 
@@ -967,7 +950,7 @@ Sql.prototype.get = async function (query, sort, view, like, timeout = 30000) {
967
950
  const timeout_promise = new Promise((unused_resolve, reject) => {
968
951
  setTimeout(() => reject(new Error('查询操作超时')), timeout);
969
952
  });
970
-
953
+
971
954
  return await Promise.race([
972
955
  (async () => {
973
956
  // 生成SQL并执行
@@ -1022,14 +1005,8 @@ Sql.prototype.addOrSet = async function (where, set, like) {
1022
1005
  }
1023
1006
  } else {
1024
1007
  for (const k in set) {
1025
- if (!Object.prototype.hasOwnProperty.call(set, k)) continue;
1026
-
1027
1008
  key += ',' + this.escapeId(k);
1028
- let val = set[k];
1029
- if (typeof val === 'string') {
1030
- val = val.trim("'");
1031
- }
1032
- value += ',' + this.escape(val);
1009
+ value += ',' + this.escape(set[k]);
1033
1010
  }
1034
1011
  }
1035
1012
 
@@ -1184,9 +1161,7 @@ Sql.prototype.toBatchAddSql = function (list) {
1184
1161
 
1185
1162
  let keys = [];
1186
1163
  for (const k in first_obj) {
1187
- if (Object.prototype.hasOwnProperty.call(first_obj, k)) {
1188
- keys.push(this.escapeId(k));
1189
- }
1164
+ keys.push(this.escapeId(k));
1190
1165
  }
1191
1166
 
1192
1167
  // 构建列名部分
@@ -1199,9 +1174,6 @@ Sql.prototype.toBatchAddSql = function (list) {
1199
1174
  for (const k of keys) {
1200
1175
  const key = k.replace(/`/g, '');
1201
1176
  let val = item[key];
1202
- if (typeof val === 'string') {
1203
- val = val.trim("'");
1204
- }
1205
1177
  values.push(this.escape(val));
1206
1178
  }
1207
1179
  values.push(`(${values.join(',')})`);
@@ -1386,15 +1358,13 @@ Sql.prototype.setList = async function (list, like = false, batch_size = 100, ti
1386
1358
  * @param {object} sql_dt sql模板集合
1387
1359
  * @returns {boolean} 有则返回true,没有则返回false
1388
1360
  */
1389
- Sql.prototype.hasPrm = function (param_dt, sql_dt) {
1361
+ Sql.prototype.has = function (param_dt, sql_dt) {
1390
1362
  var bl = false;
1391
1363
  for (var key in sql_dt) {
1392
- if (Object.prototype.hasOwnProperty.call(sql_dt, key)) {
1393
- var value = param_dt[key];
1394
- if (value !== undefined && value !== null && value !== '') {
1395
- bl = true;
1396
- break;
1397
- }
1364
+ var value = param_dt[key];
1365
+ if (value !== undefined && value !== null && value !== '') {
1366
+ bl = true;
1367
+ break;
1398
1368
  }
1399
1369
  }
1400
1370
  return bl;
@@ -1456,14 +1426,14 @@ Sql.prototype.tplQuery = function (param_dt, sql_dt) {
1456
1426
  for (var i = 0; i < len; i++) {
1457
1427
  // 使用直接替换方式,避免模板替换错误
1458
1428
  const escaped_val = this.escape(arr[i]);
1459
- sl += ' || ' + tpl.replaceAll('{0}', escaped_val);
1429
+ sl += ' || ' + tpl.replaceAll('{0}', escaped_val.trim("'"));
1460
1430
  }
1461
1431
  sl = sl.replace(' || ', '') + ')';
1462
1432
  sql += ' && ' + sl;
1463
1433
  } else {
1464
1434
  // 使用直接替换方式,避免模板替换错误
1465
1435
  const escaped_val = this.escape(value);
1466
- sql += ' && ' + tpl.replaceAll('{0}', escaped_val);
1436
+ sql += ' && ' + tpl.replaceAll('{0}', escaped_val.trim("'"));
1467
1437
  }
1468
1438
  } else {
1469
1439
  if (arr.length > 1) {
@@ -1485,7 +1455,7 @@ Sql.prototype.tplQuery = function (param_dt, sql_dt) {
1485
1455
  var value = this.escape(param_dt[key]);
1486
1456
  if (sql_dt[key]) {
1487
1457
  // 使用直接替换方式,避免模板替换错误
1488
- sql += ' && ' + sql_dt[key].replaceAll('{0}', value);
1458
+ sql += ' && ' + sql_dt[key].replaceAll('{0}', value.trim("'"));
1489
1459
  } else {
1490
1460
  sql += ' && ' + this.escapeId(key) + ' = ' + value;
1491
1461
  }
@@ -1539,7 +1509,7 @@ Sql.prototype.tplBody = function (param_dt, sql_dt) {
1539
1509
  var value = this.escape(param_dt[key]);
1540
1510
  if (sql_dt[key]) {
1541
1511
  // 使用直接替换方式,避免模板替换错误
1542
- const replaced = sql_dt[key].replace('{0}', value);
1512
+ const replaced = sql_dt[key].replaceAll('{0}', value.trim("'"));
1543
1513
  sql += ' , ' + replaced.replace('+ -', '- ').replace('- -', '+ ');
1544
1514
  } else {
1545
1515
  sql += ' , ' + this.escapeId(key) + ' = ' + value;
@@ -1636,7 +1606,7 @@ Sql.prototype.load = async function (file) {
1636
1606
  try {
1637
1607
  // 记录操作日志
1638
1608
  if (this.config && this.config.debug) {
1639
- $.log.debug(`[${this.constructor.name}] [load] 开始从文件加载数据库`, {
1609
+ this.log('debug', `开始从文件加载数据库`, {
1640
1610
  file: file
1641
1611
  });
1642
1612
  }
@@ -1672,9 +1642,9 @@ Sql.prototype.load = async function (file) {
1672
1642
  await this.exec('COMMIT');
1673
1643
 
1674
1644
  if (this.config && this.config.debug) {
1675
- $.log.info(`[${this.constructor.name}] [load] 数据库加载成功`, {
1645
+ this.log('info', `数据库加载成功`, {
1676
1646
  file: file,
1677
- stmt_num: sqlStatements.length
1647
+ stmt_num: sql_stmts.length
1678
1648
  });
1679
1649
  }
1680
1650
 
@@ -1785,12 +1755,12 @@ Sql.prototype._splitSqlStatements = function (sql_content) {
1785
1755
  * @returns {Promise<string>} 创建表的 SQL 语句
1786
1756
  * @private
1787
1757
  */
1788
- Sql.prototype._getCreateTableSql = async function() {
1758
+ Sql.prototype._getCreateTableSql = async function () {
1789
1759
  try {
1790
1760
  // 查询表结构信息(SQLite 使用 sqlite_master 表)
1791
1761
  const sql = `SELECT sql FROM sqlite_master WHERE type='table' AND name='${this.table}'`;
1792
1762
  const result = await this.run(sql);
1793
-
1763
+
1794
1764
  if (result && result.length > 0 && result[0].sql) {
1795
1765
  // 在创建表语句中添加 IF NOT EXISTS 条件
1796
1766
  let create_sql = result[0].sql;
@@ -1799,7 +1769,7 @@ Sql.prototype._getCreateTableSql = async function() {
1799
1769
  }
1800
1770
  return create_sql + ';';
1801
1771
  }
1802
-
1772
+
1803
1773
  return '';
1804
1774
  } catch (err) {
1805
1775
  this.log('warn', '获取表结构失败,将仅备份数据', err);
@@ -1813,7 +1783,7 @@ Sql.prototype._getCreateTableSql = async function() {
1813
1783
  * @param {boolean} create 是否导出创建表语句,默认为false
1814
1784
  * @returns {Promise<boolean>} 备份是否成功
1815
1785
  */
1816
- Sql.prototype.backup = async function(file, create = false) {
1786
+ Sql.prototype.backup = async function (file, create = false) {
1817
1787
  if (!file || typeof file !== 'string') {
1818
1788
  throw new TypeError('文件路径必须为字符串');
1819
1789
  }
@@ -1825,18 +1795,18 @@ Sql.prototype.backup = async function(file, create = false) {
1825
1795
  try {
1826
1796
  // 获取所有数据
1827
1797
  const data = await this.getSql('', '', '*');
1828
-
1798
+
1829
1799
  if (!data || !Array.isArray(data)) {
1830
1800
  throw new Error('获取数据失败');
1831
1801
  }
1832
1802
 
1833
1803
  // 构建 SQL 语句
1834
1804
  let sql_content = '';
1835
-
1805
+
1836
1806
  // 添加表结构(简化版,实际应用中可能需要更复杂的表结构导出)
1837
1807
  sql_content += `-- 备份表: ${this.table}\n`;
1838
1808
  sql_content += `-- 备份时间: ${new Date().toISOString()}\n\n`;
1839
-
1809
+
1840
1810
  // 如果create为true,添加创建表语句
1841
1811
  if (create) {
1842
1812
  const create_table_sql = await this._getCreateTableSql();
@@ -1844,7 +1814,7 @@ Sql.prototype.backup = async function(file, create = false) {
1844
1814
  sql_content += create_table_sql + '\n\n';
1845
1815
  }
1846
1816
  }
1847
-
1817
+
1848
1818
  // 添加数据插入语句
1849
1819
  for (const row of data) {
1850
1820
  const keys = Object.keys(row).map(key => this.escapeId(key)).join(', ');
@@ -1855,15 +1825,15 @@ Sql.prototype.backup = async function(file, create = false) {
1855
1825
  // 写入文件(这里需要文件系统模块,实际使用时需要引入 fs)
1856
1826
  const fs = require('fs');
1857
1827
  const path = require('path');
1858
-
1828
+
1859
1829
  // 确保目录存在
1860
1830
  const dir = path.dirname(file);
1861
1831
  if (!fs.existsSync(dir)) {
1862
1832
  fs.mkdirSync(dir, { recursive: true });
1863
1833
  }
1864
-
1834
+
1865
1835
  fs.writeFileSync(file, sql_content, 'utf8');
1866
-
1836
+
1867
1837
  return true;
1868
1838
  } catch (err) {
1869
1839
  this.error = err.message;
@@ -1877,7 +1847,7 @@ Sql.prototype.backup = async function(file, create = false) {
1877
1847
  * @param {string} file 备份文件路径
1878
1848
  * @returns {Promise<boolean>} 恢复是否成功
1879
1849
  */
1880
- Sql.prototype.restore = async function(file) {
1850
+ Sql.prototype.restore = async function (file) {
1881
1851
  if (!file || typeof file !== 'string') {
1882
1852
  throw new TypeError('文件路径必须为字符串');
1883
1853
  }
@@ -1888,24 +1858,24 @@ Sql.prototype.restore = async function(file) {
1888
1858
 
1889
1859
  try {
1890
1860
  const fs = require('fs');
1891
-
1861
+
1892
1862
  if (!fs.existsSync(file)) {
1893
1863
  throw new Error('备份文件不存在');
1894
1864
  }
1895
1865
 
1896
1866
  // 读取 SQL 文件
1897
1867
  const sql_content = fs.readFileSync(file, 'utf8');
1898
-
1868
+
1899
1869
  // 解析 SQL 语句
1900
1870
  const stmts = this._parseSqlStatements(sql_content);
1901
-
1871
+
1902
1872
  // 执行每个 SQL 语句
1903
1873
  for (const stmt of stmts) {
1904
1874
  if (stmt.trim() && !stmt.startsWith('--')) {
1905
1875
  await this.exec(stmt);
1906
1876
  }
1907
1877
  }
1908
-
1878
+
1909
1879
  return true;
1910
1880
  } catch (err) {
1911
1881
  this.error = err.message;
@@ -1920,7 +1890,7 @@ Sql.prototype.restore = async function(file) {
1920
1890
  * @returns {string[]} SQL 语句数组
1921
1891
  * @private
1922
1892
  */
1923
- Sql.prototype._parseSqlStatements = function(sql) {
1893
+ Sql.prototype._parseSqlStatements = function (sql) {
1924
1894
  const stmts = [];
1925
1895
  let cur_stmt = '';
1926
1896
  let in_str = false;
Binary file
Binary file
File without changes
Binary file
package/test_backup.js DELETED
@@ -1,78 +0,0 @@
1
- /**
2
- * @fileOverview 备份恢复功能测试脚本
3
- * @version 1.0
4
- */
5
-
6
- const {Sql} = require('./sql');
7
-
8
-
9
- // 模拟数据库操作函数
10
- async function mockRun(sql) {
11
- console.log('执行查询SQL:', sql);
12
-
13
- // 模拟返回数据
14
- if (sql.includes('SELECT')) {
15
- return [
16
- { id: 1, name: '张三', age: 25 },
17
- { id: 2, name: '李四', age: 30 },
18
- { id: 3, name: '王五', age: 28 }
19
- ];
20
- }
21
-
22
- if (sql.includes('count')) {
23
- return [{ count: 3 }];
24
- }
25
-
26
- return [];
27
- }
28
-
29
- async function mockExec(sql) {
30
- console.log('执行更新SQL:', sql);
31
- return { affectedRows: 1, insertId: 1 };
32
- }
33
-
34
- async function testBackupRestore() {
35
- console.log('=== 测试备份恢复功能 ===');
36
-
37
- // 创建 SQL 实例
38
- const sql = new Sql(mockRun, mockExec);
39
- sql.table = 'test_table';
40
-
41
- const backupFile = './backup/test_backup.sql';
42
-
43
- try {
44
- // 测试备份
45
- console.log('\n1. 测试备份功能...');
46
- const backupResult = await sql.backup(backupFile);
47
- console.log('备份结果:', backupResult ? '成功' : '失败');
48
-
49
- if (backupResult) {
50
- // 读取备份文件内容
51
- const fs = require('fs');
52
- if (fs.existsSync(backupFile)) {
53
- const content = fs.readFileSync(backupFile, 'utf8');
54
- console.log('备份文件内容:');
55
- console.log(content);
56
- }
57
- }
58
-
59
- // 测试恢复
60
- console.log('\n2. 测试恢复功能...');
61
- const restoreResult = await sql.restore(backupFile);
62
- console.log('恢复结果:', restoreResult ? '成功' : '失败');
63
-
64
- console.log('\n=== 测试完成 ===');
65
-
66
- } catch (error) {
67
- console.error('测试出错:', error.message);
68
- }
69
- }
70
-
71
- // 运行测试
72
- if (require.main === module) {
73
- testBackupRestore();
74
- }
75
-
76
- module.exports = {
77
- testBackupRestore
78
- };
@@ -1,86 +0,0 @@
1
- /**
2
- * SQLite SQL函数测试文件
3
- * @file test_sql_functions.js
4
- * @description 直接测试Sql类的SQL生成函数,不涉及数据库连接
5
- */
6
-
7
- // 引入依赖
8
- const { Sql } = require('./sql.js');
9
-
10
- function test() {
11
- console.log('=== 测试SQLite SQL函数 ===\n');
12
-
13
- // 创建Sql实例
14
- const db = new Sql(null, null);
15
- db.table = 'test_table';
16
-
17
- // 测试1: 测试toQuery函数
18
- console.log('1. 测试toQuery函数:');
19
- const query_sql = db.toQuery('`id` = 1', '`id` DESC', 'title, regex_field');
20
- console.log(' toQuery生成的SQL:', query_sql);
21
-
22
- // 测试2: 测试包含特殊字符的查询
23
- console.log('\n2. 测试包含特殊字符的查询:');
24
- const special_query = db.toQuery('`title` LIKE \'%test%\'', null, '*');
25
- console.log(' 特殊字符查询SQL:', special_query);
26
-
27
- // 测试3: 测试toAddSql函数
28
- console.log('\n3. 测试toAddSql函数:');
29
- const add_sql = db.toAddSql({
30
- title: '测试添加标题',
31
- content: '测试添加内容',
32
- regex_field: '~\\d+$',
33
- special_chars: "'test' AND 1=1"
34
- });
35
- console.log(' toAddSql生成的SQL:', add_sql);
36
-
37
- // 测试4: 测试toSetSql函数
38
- console.log('\n4. 测试toSetSql函数:');
39
- const set_sql = db.toSetSql(
40
- { id: 1 },
41
- { title: '更新标题', regex_field: '~\\d+$' }
42
- );
43
- console.log(' toSetSql生成的SQL:', set_sql);
44
-
45
- // 测试5: 测试toDelSql函数
46
- console.log('\n5. 测试toDelSql函数:');
47
- const del_sql = db.toDelSql({ id: 999 });
48
- console.log(' toDelSql生成的SQL:', del_sql);
49
-
50
- // 测试6: 测试toWhere函数
51
- console.log('\n6. 测试toWhere函数:');
52
- const where_sql = db.toWhere({
53
- id: 1,
54
- title_like: 'test',
55
- regex_field: '~\\d+$'
56
- });
57
- console.log(' toWhere生成的SQL:', where_sql);
58
-
59
- // 测试7: 测试toSet函数
60
- console.log('\n7. 测试toSet函数:');
61
- const set_str = db.toSet({
62
- title: '新标题',
63
- content: '新内容',
64
- regex_field: '~\\d+$'
65
- });
66
- console.log(' toSet生成的SQL:', set_str);
67
-
68
- // 测试8: 测试addSql函数(只生成SQL,不执行)
69
- console.log('\n8. 测试addSql函数:');
70
- const add_sql_str = `INSERT INTO \`${db.table}\` (\`title\`, \`content\`, \`regex_field\`) VALUES ('测试标题', '测试内容', '~\\\\d+$');`;
71
- console.log(' addSql生成的SQL:', add_sql_str);
72
-
73
- // 测试9: 测试setSql函数(只生成SQL,不执行)
74
- console.log('\n9. 测试setSql函数:');
75
- const set_sql_str = `UPDATE \`${db.table}\` SET \`title\` = '更新标题', \`regex_field\` = '~\\\\d+$' WHERE \`id\` = 1;`;
76
- console.log(' setSql生成的SQL:', set_sql_str);
77
-
78
- // 测试10: 测试delSql函数(只生成SQL,不执行)
79
- console.log('\n10. 测试delSql函数:');
80
- const del_sql_str = `DELETE FROM \`${db.table}\` WHERE \`id\` = 999;`;
81
- console.log(' delSql生成的SQL:', del_sql_str);
82
-
83
- console.log('\n=== 所有SQL函数测试完成 ===');
84
- }
85
-
86
- test();
package/test_sqlite.js DELETED
@@ -1,104 +0,0 @@
1
- /**
2
- * SQLite数据库操作类测试文件
3
- * @file test_sqlite.js
4
- * @description 测试Sqlite类的各项功能,特别是正则表达式写入
5
- */
6
-
7
- // 引入依赖
8
- const { SQLite } = require('./index.js');
9
-
10
- async function test() {
11
- const sqlite = new SQLite({
12
- file: ':memory:', // 使用内存数据库进行测试
13
- debug: true
14
- });
15
-
16
- await sqlite.open();
17
- console.log('SQLite数据库连接成功');
18
-
19
- // 创建测试表
20
- await sqlite.exec(`
21
- CREATE TABLE IF NOT EXISTS test_table (
22
- id INTEGER PRIMARY KEY AUTOINCREMENT,
23
- title TEXT,
24
- content TEXT,
25
- regex_field TEXT,
26
- special_chars TEXT
27
- )
28
- `);
29
- console.log('测试表创建成功');
30
-
31
- const db = sqlite.db();
32
- db.table = 'test_table';
33
-
34
- console.log('=== 测试SQLite数据库操作 ===\n');
35
-
36
- // 测试1: 普通字符串写入
37
- console.log('1. 测试普通字符串写入:');
38
- const result1 = await db.set({
39
- id: 1
40
- }, {
41
- title: "测试标题",
42
- content: "测试内容"
43
- });
44
- console.log(' 普通字符串更新结果:', result1, db.error);
45
-
46
- // 测试2: 正则表达式字符串写入
47
- console.log('\n2. 测试正则表达式字符串写入:');
48
- const regex_str = "~\\d+$";
49
- console.log(' 正则表达式字符串:', regex_str);
50
-
51
- const result2 = await db.set({
52
- id: 1
53
- }, {
54
- title: regex_str,
55
- regex_field: regex_str
56
- });
57
- console.log(' 正则表达式更新结果:', result2, db.error);
58
-
59
- // 测试3: 查看当前数据库中的值
60
- console.log('\n3. 查看当前数据:');
61
- const data = await db.get({
62
- id: 1
63
- });
64
- console.log(' 当前数据:', data);
65
-
66
- // 测试4: 测试toQuery函数
67
- console.log('\n4. 测试toQuery函数:');
68
- const query_sql = db.toQuery('`id` = 1', '`id` DESC', 'title, regex_field');
69
- console.log(' toQuery生成的SQL:', query_sql);
70
-
71
- // 测试5: 测试包含特殊字符的查询
72
- console.log('\n5. 测试包含特殊字符的查询:');
73
- const special_query = db.toQuery('`title` LIKE \'%test%\'', null, '*');
74
- console.log(' 特殊字符查询SQL:', special_query);
75
-
76
- // 测试6: 测试toAddSql函数
77
- console.log('\n6. 测试toAddSql函数:');
78
- const add_sql = db.toAddSql({
79
- title: '测试添加标题',
80
- content: '测试添加内容',
81
- regex_field: '~\\d+$',
82
- special_chars: "'test' AND 1=1"
83
- });
84
- console.log(' toAddSql生成的SQL:', add_sql);
85
-
86
- // 测试7: 测试toSetSql函数
87
- console.log('\n7. 测试toSetSql函数:');
88
- const set_sql = db.toSetSql(
89
- { id: 1 },
90
- { title: '更新标题', regex_field: '~\\d+$' }
91
- );
92
- console.log(' toSetSql生成的SQL:', set_sql);
93
-
94
- // 测试8: 测试toDelSql函数
95
- console.log('\n8. 测试toDelSql函数:');
96
- const del_sql = db.toDelSql({ id: 999 });
97
- console.log(' toDelSql生成的SQL:', del_sql);
98
-
99
- console.log('\n=== 所有SQLite函数测试完成 ===');
100
-
101
- await sqlite.close();
102
- }
103
-
104
- test().catch(console.error);