mm_sqlite 1.4.3 → 1.4.5
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 +2 -2
- package/package.json +4 -4
- package/sql.js +91 -91
- package/test_db/test_basic.db +0 -0
- package/test_db/test_core_methods.db +0 -0
package/index.js
CHANGED
|
@@ -209,7 +209,7 @@ SQLite.prototype.run = async function (sql, params = [], timeout = 30000) {
|
|
|
209
209
|
});
|
|
210
210
|
});
|
|
211
211
|
} catch (error) {
|
|
212
|
-
|
|
212
|
+
console.error('SQL执行失败', error);
|
|
213
213
|
this.sql = sql;
|
|
214
214
|
this.error = {
|
|
215
215
|
code: error.errno,
|
|
@@ -275,7 +275,7 @@ SQLite.prototype.exec = async function (sql, params, timeout) {
|
|
|
275
275
|
});
|
|
276
276
|
});
|
|
277
277
|
} catch (error) {
|
|
278
|
-
|
|
278
|
+
console.error('SQL执行失败', error);
|
|
279
279
|
this.sql = sql;
|
|
280
280
|
this.error = {
|
|
281
281
|
code: error.errno,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mm_sqlite",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.5",
|
|
4
4
|
"description": "高性能SQLite数据库操作模块,提供与mm_mysql完全兼容的API接口,支持异步操作、事务处理和批量操作",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
"node": ">=14.0.0"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"mm_expand": "^2.3.
|
|
41
|
+
"mm_expand": "^2.3.4",
|
|
42
42
|
"sqlite3": "^6.0.1",
|
|
43
43
|
"sqlstring": "^2.3.3"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"eslint": "^10.
|
|
47
|
-
"eslint-plugin-jsdoc": "^
|
|
46
|
+
"eslint": "^10.4.0",
|
|
47
|
+
"eslint-plugin-jsdoc": "^63.0.0",
|
|
48
48
|
"mm_eslint": "^1.7.1"
|
|
49
49
|
}
|
|
50
50
|
}
|
package/sql.js
CHANGED
|
@@ -468,8 +468,8 @@ Sql.prototype.sum = async function (field, query) {
|
|
|
468
468
|
throw new TypeError('表名未设置');
|
|
469
469
|
}
|
|
470
470
|
|
|
471
|
-
|
|
472
|
-
|
|
471
|
+
let result = await this.groupSum(query, '', field, '');
|
|
472
|
+
let fieldKey = 'sum_' + field.replace(/`/g, '');
|
|
473
473
|
return result && result.length > 0 ? Number(result[0][fieldKey] || result[0].sum_age) : 0;
|
|
474
474
|
};
|
|
475
475
|
|
|
@@ -488,8 +488,8 @@ Sql.prototype.max = async function (field, query) {
|
|
|
488
488
|
throw new TypeError('表名未设置');
|
|
489
489
|
}
|
|
490
490
|
|
|
491
|
-
|
|
492
|
-
|
|
491
|
+
let result = await this.groupMath(query, '', field, '', 'MAX');
|
|
492
|
+
let fieldKey = 'max_' + field.replace(/`/g, '');
|
|
493
493
|
return result && result.length > 0 ? Number(result[0][fieldKey] || result[0].max_age) : 0;
|
|
494
494
|
};
|
|
495
495
|
|
|
@@ -508,8 +508,8 @@ Sql.prototype.min = async function (field, query) {
|
|
|
508
508
|
throw new TypeError('表名未设置');
|
|
509
509
|
}
|
|
510
510
|
|
|
511
|
-
|
|
512
|
-
|
|
511
|
+
let result = await this.groupMath(query, '', field, '', 'MIN');
|
|
512
|
+
let fieldKey = 'min_' + field.replace(/`/g, '');
|
|
513
513
|
return result && result.length > 0 ? Number(result[0][fieldKey] || result[0].min_age) : 0;
|
|
514
514
|
};
|
|
515
515
|
|
|
@@ -528,8 +528,8 @@ Sql.prototype.avg = async function (field, query) {
|
|
|
528
528
|
throw new TypeError('表名未设置');
|
|
529
529
|
}
|
|
530
530
|
|
|
531
|
-
|
|
532
|
-
|
|
531
|
+
let result = await this.groupMath(query, '', field, '', 'AVG');
|
|
532
|
+
let fieldKey = 'avg_' + field.replace(/`/g, '');
|
|
533
533
|
return result && result.length > 0 ? Number(result[0][fieldKey] || result[0].avg_age) : 0;
|
|
534
534
|
};
|
|
535
535
|
|
|
@@ -565,7 +565,7 @@ Sql.prototype.backup = async function (file) {
|
|
|
565
565
|
}
|
|
566
566
|
|
|
567
567
|
// 获取所有数据
|
|
568
|
-
|
|
568
|
+
let data = await this.getSql('', '', '*');
|
|
569
569
|
|
|
570
570
|
if (!data || !Array.isArray(data)) {
|
|
571
571
|
throw new Error('获取数据失败');
|
|
@@ -579,18 +579,18 @@ Sql.prototype.backup = async function (file) {
|
|
|
579
579
|
sqlContent += `-- 备份时间: ${new Date().toISOString()}\n\n`;
|
|
580
580
|
|
|
581
581
|
// 添加数据插入语句
|
|
582
|
-
for (
|
|
583
|
-
|
|
584
|
-
|
|
582
|
+
for (let row of data) {
|
|
583
|
+
let keys = Object.keys(row).map(key => this.escapeId(key)).join(', ');
|
|
584
|
+
let values = Object.values(row).map(value => this.escape(value)).join(', ');
|
|
585
585
|
sqlContent += `INSERT INTO \`${this.table}\` (${keys}) VALUES (${values});\n`;
|
|
586
586
|
}
|
|
587
587
|
|
|
588
588
|
// 写入文件(这里需要文件系统模块,实际使用时需要引入 fs)
|
|
589
|
-
|
|
590
|
-
|
|
589
|
+
let fs = require('fs');
|
|
590
|
+
let path = require('path');
|
|
591
591
|
|
|
592
592
|
// 确保目录存在
|
|
593
|
-
|
|
593
|
+
let dir = path.dirname(file);
|
|
594
594
|
if (!fs.existsSync(dir)) {
|
|
595
595
|
fs.mkdirSync(dir, { recursive: true });
|
|
596
596
|
}
|
|
@@ -614,7 +614,7 @@ Sql.prototype.restore = async function (file) {
|
|
|
614
614
|
throw new TypeError('表名未设置');
|
|
615
615
|
}
|
|
616
616
|
|
|
617
|
-
|
|
617
|
+
let fs = require('fs');
|
|
618
618
|
|
|
619
619
|
// 检查文件是否存在
|
|
620
620
|
if (!fs.existsSync(file)) {
|
|
@@ -622,17 +622,17 @@ Sql.prototype.restore = async function (file) {
|
|
|
622
622
|
}
|
|
623
623
|
|
|
624
624
|
// 读取文件内容
|
|
625
|
-
|
|
625
|
+
let sqlContent = fs.readFileSync(file, 'utf8');
|
|
626
626
|
|
|
627
627
|
if (!sqlContent) {
|
|
628
628
|
throw new Error('备份文件为空');
|
|
629
629
|
}
|
|
630
630
|
|
|
631
631
|
// 解析 SQL 语句(按分号分割,但需要处理字符串中的分号)
|
|
632
|
-
|
|
632
|
+
let statements = this._parseSqlStatements(sqlContent);
|
|
633
633
|
|
|
634
634
|
// 执行所有 SQL 语句
|
|
635
|
-
for (
|
|
635
|
+
for (let statement of statements) {
|
|
636
636
|
if (statement.trim()) {
|
|
637
637
|
// 跳过注释行
|
|
638
638
|
if (!statement.trim().startsWith('--')) {
|
|
@@ -651,13 +651,13 @@ Sql.prototype.restore = async function (file) {
|
|
|
651
651
|
* @private
|
|
652
652
|
*/
|
|
653
653
|
Sql.prototype._parseSqlStatements = function (sql) {
|
|
654
|
-
|
|
654
|
+
let statements = [];
|
|
655
655
|
let currentStatement = '';
|
|
656
656
|
let inString = false;
|
|
657
657
|
let stringChar = '';
|
|
658
658
|
|
|
659
659
|
for (let i = 0; i < sql.length; i++) {
|
|
660
|
-
|
|
660
|
+
let char = sql[i];
|
|
661
661
|
|
|
662
662
|
if (char === "'" || char === '"') {
|
|
663
663
|
if (!inString) {
|
|
@@ -745,7 +745,7 @@ Sql.prototype.toWhere = function (obj, like) {
|
|
|
745
745
|
}
|
|
746
746
|
}
|
|
747
747
|
}
|
|
748
|
-
return where.replace(
|
|
748
|
+
return where.replace(/^ and /, '');
|
|
749
749
|
};
|
|
750
750
|
|
|
751
751
|
/**
|
|
@@ -770,7 +770,7 @@ Sql.prototype.toSet = function (obj) {
|
|
|
770
770
|
set += ',' + escapeId(k) + ' = ' + val;
|
|
771
771
|
}
|
|
772
772
|
}
|
|
773
|
-
return set.replace(
|
|
773
|
+
return set.replace(/^,/, '');
|
|
774
774
|
};
|
|
775
775
|
|
|
776
776
|
/**
|
|
@@ -786,14 +786,14 @@ Sql.prototype.toAddSql = function (item) {
|
|
|
786
786
|
let key = '';
|
|
787
787
|
let value = '';
|
|
788
788
|
|
|
789
|
-
for (
|
|
789
|
+
for (let k in item) {
|
|
790
790
|
key += ',' + escapeId(k);
|
|
791
791
|
let val = item[k];
|
|
792
792
|
value += ',' + escape(val);
|
|
793
793
|
}
|
|
794
794
|
|
|
795
795
|
// 使用直接拼接的方式,避免模板替换错误
|
|
796
|
-
|
|
796
|
+
let sql = `INSERT INTO \`${this.table}\` (${key.replace(',', '')}) VALUES (${value.replace(',', '')});`;
|
|
797
797
|
|
|
798
798
|
return sql;
|
|
799
799
|
};
|
|
@@ -808,10 +808,10 @@ Sql.prototype.toDelSql = function (query, like) {
|
|
|
808
808
|
if (!this.table) {
|
|
809
809
|
throw new Error('表名未设置');
|
|
810
810
|
}
|
|
811
|
-
|
|
811
|
+
let where = this.toWhere(query, like);
|
|
812
812
|
|
|
813
813
|
// 使用直接拼接的方式,避免模板替换错误
|
|
814
|
-
|
|
814
|
+
let sql = `DELETE FROM \`${this.table}\` WHERE ${where};`;
|
|
815
815
|
|
|
816
816
|
return sql;
|
|
817
817
|
};
|
|
@@ -827,11 +827,11 @@ Sql.prototype.toSetSql = function (query, item, like) {
|
|
|
827
827
|
if (!this.table) {
|
|
828
828
|
throw new Error('表名未设置');
|
|
829
829
|
}
|
|
830
|
-
|
|
831
|
-
|
|
830
|
+
let where = this.toWhere(query, like);
|
|
831
|
+
let set = this.toSet(item);
|
|
832
832
|
|
|
833
833
|
// 使用直接拼接的方式,避免模板替换错误
|
|
834
|
-
|
|
834
|
+
let sql = `UPDATE \`${this.table}\` SET ${set} WHERE ${where};`;
|
|
835
835
|
|
|
836
836
|
return sql;
|
|
837
837
|
};
|
|
@@ -935,29 +935,29 @@ Sql.prototype.addOrSet = async function (where, set, like) {
|
|
|
935
935
|
where_str = where;
|
|
936
936
|
}
|
|
937
937
|
|
|
938
|
-
|
|
938
|
+
let count = await this.countSql(where_str);
|
|
939
939
|
|
|
940
940
|
if (count === 0) {
|
|
941
941
|
let key = '';
|
|
942
942
|
let value = '';
|
|
943
943
|
|
|
944
944
|
if (typeof set === 'string') {
|
|
945
|
-
|
|
946
|
-
for (
|
|
947
|
-
|
|
945
|
+
let arr = set.split(',');
|
|
946
|
+
for (let o of arr) {
|
|
947
|
+
let ar = o.split('=');
|
|
948
948
|
if (ar.length === 2) {
|
|
949
949
|
key += ',' + ar[0];
|
|
950
950
|
value += ',' + ar[1];
|
|
951
951
|
}
|
|
952
952
|
}
|
|
953
953
|
} else {
|
|
954
|
-
for (
|
|
954
|
+
for (let k in set) {
|
|
955
955
|
key += ',' + this.escapeId(k);
|
|
956
956
|
value += ',' + this.escape(set[k]);
|
|
957
957
|
}
|
|
958
958
|
}
|
|
959
959
|
|
|
960
|
-
|
|
960
|
+
let bl = await this.addSql(key.replace(',', ''), value.replace(',', ''));
|
|
961
961
|
|
|
962
962
|
return bl;
|
|
963
963
|
} else {
|
|
@@ -966,7 +966,7 @@ Sql.prototype.addOrSet = async function (where, set, like) {
|
|
|
966
966
|
set_vals = await this.toSet(set);
|
|
967
967
|
}
|
|
968
968
|
|
|
969
|
-
|
|
969
|
+
let bl1 = await this.setSql(where_str, set_vals);
|
|
970
970
|
|
|
971
971
|
return bl1;
|
|
972
972
|
}
|
|
@@ -984,11 +984,11 @@ Sql.prototype.count = async function (query, like, timeout = 30000) {
|
|
|
984
984
|
throw new Error('表名未设置');
|
|
985
985
|
}
|
|
986
986
|
|
|
987
|
-
|
|
988
|
-
|
|
987
|
+
let where = typeof query === 'string' ? query : await this.toWhere(query, like);
|
|
988
|
+
let sql = 'SELECT COUNT(*) as num FROM `' + this.table + '`' + (where ? ' WHERE ' + where : '');
|
|
989
989
|
this.sql = sql;
|
|
990
|
-
|
|
991
|
-
|
|
990
|
+
let list = await this.run(sql);
|
|
991
|
+
let total = list && list[0] && list[0].num ? parseInt(list[0].num) : 0;
|
|
992
992
|
|
|
993
993
|
return total;
|
|
994
994
|
};
|
|
@@ -1023,17 +1023,17 @@ Sql.prototype.addList = async function (list, batch_size = 100, timeout = 60000)
|
|
|
1023
1023
|
}
|
|
1024
1024
|
|
|
1025
1025
|
// 分批处理大数据量
|
|
1026
|
-
|
|
1026
|
+
let total = Math.ceil(list.length / batch_size);
|
|
1027
1027
|
this.log('info', `开始分批添加数据,共${total}批,每批${batch_size}条`);
|
|
1028
1028
|
|
|
1029
1029
|
// 分批执行,每批一个单独的批量插入语句
|
|
1030
1030
|
let final_res = null;
|
|
1031
1031
|
for (let i = 0; i < total; i++) {
|
|
1032
|
-
|
|
1032
|
+
let batch = list.slice(i * batch_size, (i + 1) * batch_size);
|
|
1033
1033
|
this.log('debug', `处理第${i + 1}/${total}批数据,${batch.length}条`);
|
|
1034
1034
|
|
|
1035
1035
|
// 生成批量插入SQL
|
|
1036
|
-
|
|
1036
|
+
let batch_sql = this.toBatchAddSql(batch);
|
|
1037
1037
|
this.sql = batch_sql;
|
|
1038
1038
|
|
|
1039
1039
|
final_res = await this.exec(batch_sql);
|
|
@@ -1054,25 +1054,25 @@ Sql.prototype.toBatchAddSql = function (list) {
|
|
|
1054
1054
|
}
|
|
1055
1055
|
|
|
1056
1056
|
// 获取第一个对象的键名作为列名
|
|
1057
|
-
|
|
1057
|
+
let first_obj = list[0];
|
|
1058
1058
|
if (!first_obj || typeof first_obj !== 'object') {
|
|
1059
1059
|
throw new Error('数据格式错误');
|
|
1060
1060
|
}
|
|
1061
1061
|
|
|
1062
1062
|
let keys = [];
|
|
1063
|
-
for (
|
|
1063
|
+
for (let k in first_obj) {
|
|
1064
1064
|
keys.push(this.escapeId(k));
|
|
1065
1065
|
}
|
|
1066
1066
|
|
|
1067
1067
|
// 构建列名部分
|
|
1068
|
-
|
|
1068
|
+
let columns = keys.join(',');
|
|
1069
1069
|
|
|
1070
1070
|
// 构建值部分
|
|
1071
|
-
|
|
1072
|
-
for (
|
|
1073
|
-
|
|
1074
|
-
for (
|
|
1075
|
-
|
|
1071
|
+
let values = [];
|
|
1072
|
+
for (let item of list) {
|
|
1073
|
+
let values = [];
|
|
1074
|
+
for (let k of keys) {
|
|
1075
|
+
let key = k.replace(/`/g, '');
|
|
1076
1076
|
let val = item[key];
|
|
1077
1077
|
values.push(this.escape(val));
|
|
1078
1078
|
}
|
|
@@ -1080,7 +1080,7 @@ Sql.prototype.toBatchAddSql = function (list) {
|
|
|
1080
1080
|
}
|
|
1081
1081
|
|
|
1082
1082
|
// 生成最终SQL
|
|
1083
|
-
|
|
1083
|
+
let sql = `INSERT INTO \`${this.table}\` (${columns}) VALUES ${values.join(',')}`;
|
|
1084
1084
|
return sql;
|
|
1085
1085
|
};
|
|
1086
1086
|
|
|
@@ -1098,7 +1098,7 @@ Sql.prototype.delList = async function (list, like, batch_size = 100, timeout =
|
|
|
1098
1098
|
}
|
|
1099
1099
|
if (list.length <= batch_size) {
|
|
1100
1100
|
let sql = '';
|
|
1101
|
-
for (
|
|
1101
|
+
for (let item of list) {
|
|
1102
1102
|
sql += this.toDelSql(item.query, like);
|
|
1103
1103
|
}
|
|
1104
1104
|
this.sql = sql;
|
|
@@ -1106,7 +1106,7 @@ Sql.prototype.delList = async function (list, like, batch_size = 100, timeout =
|
|
|
1106
1106
|
}
|
|
1107
1107
|
|
|
1108
1108
|
// 分批处理大数据量
|
|
1109
|
-
|
|
1109
|
+
let total = Math.ceil(list.length / batch_size);
|
|
1110
1110
|
this.log('info', `开始分批删除数据,共${total}批,每批${batch_size}条`);
|
|
1111
1111
|
|
|
1112
1112
|
// 使用事务包装整个操作以保证原子性
|
|
@@ -1117,11 +1117,11 @@ Sql.prototype.delList = async function (list, like, batch_size = 100, timeout =
|
|
|
1117
1117
|
|
|
1118
1118
|
// 分批处理
|
|
1119
1119
|
for (let i = 0; i < total; i++) {
|
|
1120
|
-
|
|
1120
|
+
let batch = list.slice(i * batch_size, (i + 1) * batch_size);
|
|
1121
1121
|
this.log('debug', `处理第${i + 1}/${total}批数据,${batch.length}条`);
|
|
1122
1122
|
|
|
1123
1123
|
let batch_sql = '';
|
|
1124
|
-
for (
|
|
1124
|
+
for (let item of batch) {
|
|
1125
1125
|
batch_sql += this.toDelSql(item.query, like);
|
|
1126
1126
|
}
|
|
1127
1127
|
final_res = await this.exec(batch_sql, [], timeout);
|
|
@@ -1158,7 +1158,7 @@ Sql.prototype.setList = async function (list, like = false, batch_size = 100, ti
|
|
|
1158
1158
|
}
|
|
1159
1159
|
if (list.length <= batch_size) {
|
|
1160
1160
|
let sql = '';
|
|
1161
|
-
for (
|
|
1161
|
+
for (let item of list) {
|
|
1162
1162
|
sql += this.toSetSql(item.query, item.obj, like);
|
|
1163
1163
|
}
|
|
1164
1164
|
this.sql = sql;
|
|
@@ -1166,7 +1166,7 @@ Sql.prototype.setList = async function (list, like = false, batch_size = 100, ti
|
|
|
1166
1166
|
}
|
|
1167
1167
|
|
|
1168
1168
|
// 分批处理大数据量
|
|
1169
|
-
|
|
1169
|
+
let total = Math.ceil(list.length / batch_size);
|
|
1170
1170
|
this.log('info', `开始分批更新数据,共${total}批,每批${batch_size}条`);
|
|
1171
1171
|
|
|
1172
1172
|
// 使用事务包装整个操作以保证原子性
|
|
@@ -1177,11 +1177,11 @@ Sql.prototype.setList = async function (list, like = false, batch_size = 100, ti
|
|
|
1177
1177
|
|
|
1178
1178
|
// 分批处理
|
|
1179
1179
|
for (let i = 0; i < total; i++) {
|
|
1180
|
-
|
|
1180
|
+
let batch = list.slice(i * batch_size, (i + 1) * batch_size);
|
|
1181
1181
|
this.log('debug', `处理第${i + 1}/${total}批数据,${batch.length}条`);
|
|
1182
1182
|
|
|
1183
1183
|
let batch_sql = '';
|
|
1184
|
-
for (
|
|
1184
|
+
for (let item of batch) {
|
|
1185
1185
|
batch_sql += this.toSetSql(item.query, item.obj, like);
|
|
1186
1186
|
}
|
|
1187
1187
|
|
|
@@ -1274,14 +1274,14 @@ Sql.prototype.tplQuery = function (param_dt, sql_dt) {
|
|
|
1274
1274
|
var len = arr.length;
|
|
1275
1275
|
for (var i = 0; i < len; i++) {
|
|
1276
1276
|
// 使用直接替换方式,避免模板替换错误
|
|
1277
|
-
|
|
1277
|
+
let escaped_val = this.escape(arr[i]);
|
|
1278
1278
|
sl += ' || ' + tpl.replaceAll('{0}', escaped_val.trim("'"));
|
|
1279
1279
|
}
|
|
1280
1280
|
sl = sl.replace(' || ', '') + ')';
|
|
1281
1281
|
sql += ' && ' + sl;
|
|
1282
1282
|
} else {
|
|
1283
1283
|
// 使用直接替换方式,避免模板替换错误
|
|
1284
|
-
|
|
1284
|
+
let escaped_val = this.escape(value);
|
|
1285
1285
|
sql += ' && ' + tpl.replaceAll('{0}', escaped_val.trim("'"));
|
|
1286
1286
|
}
|
|
1287
1287
|
} else {
|
|
@@ -1358,7 +1358,7 @@ Sql.prototype.tplBody = function (param_dt, sql_dt) {
|
|
|
1358
1358
|
var value = this.escape(param_dt[key]);
|
|
1359
1359
|
if (sql_dt[key]) {
|
|
1360
1360
|
// 使用直接替换方式,避免模板替换错误
|
|
1361
|
-
|
|
1361
|
+
let replaced = sql_dt[key].replaceAll('{0}', value.trim("'"));
|
|
1362
1362
|
sql += ' , ' + replaced.replace('+ -', '- ').replace('- -', '+ ');
|
|
1363
1363
|
} else {
|
|
1364
1364
|
sql += ' , ' + this.escapeId(key) + ' = ' + value;
|
|
@@ -1415,15 +1415,15 @@ Sql.prototype.model = function (model) {
|
|
|
1415
1415
|
*/
|
|
1416
1416
|
Sql.prototype.getObj = async function (query, sort, view, like, timeout = 30000) {
|
|
1417
1417
|
// 保存当前分页设置
|
|
1418
|
-
|
|
1419
|
-
|
|
1418
|
+
let old_page = this.page;
|
|
1419
|
+
let size = this.size;
|
|
1420
1420
|
|
|
1421
1421
|
// 设置为只查询一条
|
|
1422
1422
|
this.page = 1;
|
|
1423
1423
|
this.size = 1;
|
|
1424
1424
|
|
|
1425
1425
|
// 使用优化后的get方法
|
|
1426
|
-
|
|
1426
|
+
let list = await this.get(query, sort, view, like, timeout);
|
|
1427
1427
|
|
|
1428
1428
|
// 恢复分页设置
|
|
1429
1429
|
this.page = old_page;
|
|
@@ -1459,22 +1459,22 @@ Sql.prototype.load = async function (file) {
|
|
|
1459
1459
|
}
|
|
1460
1460
|
|
|
1461
1461
|
// 读取SQL文件内容
|
|
1462
|
-
|
|
1462
|
+
let sql_content = await $.file.readText(file);
|
|
1463
1463
|
|
|
1464
1464
|
if (!sql_content || sql_content.trim() === '') {
|
|
1465
1465
|
throw new Error(`SQL文件内容为空: ${file}`);
|
|
1466
1466
|
}
|
|
1467
1467
|
|
|
1468
1468
|
// 分割SQL语句(按分号分割,但需要注意处理字符串中的分号)
|
|
1469
|
-
|
|
1469
|
+
let sql_stmts = this._splitSqlStatements(sql_content);
|
|
1470
1470
|
|
|
1471
1471
|
// 开始事务执行SQL语句
|
|
1472
1472
|
await this.exec('BEGIN TRANSACTION');
|
|
1473
1473
|
|
|
1474
1474
|
try {
|
|
1475
1475
|
// 逐个执行SQL语句
|
|
1476
|
-
for (
|
|
1477
|
-
|
|
1476
|
+
for (let sql of sql_stmts) {
|
|
1477
|
+
let trim_sql = sql.trim();
|
|
1478
1478
|
if (trim_sql) {
|
|
1479
1479
|
await this.exec(trim_sql);
|
|
1480
1480
|
}
|
|
@@ -1510,15 +1510,15 @@ Sql.prototype.load = async function (file) {
|
|
|
1510
1510
|
* @returns {Array} SQL语句数组
|
|
1511
1511
|
*/
|
|
1512
1512
|
Sql.prototype._splitSqlStatements = function (sql_content) {
|
|
1513
|
-
|
|
1513
|
+
let stmts = [];
|
|
1514
1514
|
let in_str = false;
|
|
1515
1515
|
let str_char = '';
|
|
1516
1516
|
let in_cmt = false;
|
|
1517
1517
|
let cur_stmt = '';
|
|
1518
1518
|
|
|
1519
1519
|
for (let i = 0; i < sql_content.length; i++) {
|
|
1520
|
-
|
|
1521
|
-
|
|
1520
|
+
let char = sql_content[i];
|
|
1521
|
+
let next_char = i + 1 < sql_content.length ? sql_content[i + 1] : '';
|
|
1522
1522
|
|
|
1523
1523
|
// 处理注释
|
|
1524
1524
|
if (!in_str && !in_cmt && char === '-' && next_char === '-') {
|
|
@@ -1596,8 +1596,8 @@ Sql.prototype._splitSqlStatements = function (sql_content) {
|
|
|
1596
1596
|
*/
|
|
1597
1597
|
Sql.prototype._getCreateTableSql = async function () {
|
|
1598
1598
|
// 查询表结构信息(SQLite 使用 sqlite_master 表)
|
|
1599
|
-
|
|
1600
|
-
|
|
1599
|
+
let sql = `SELECT sql FROM sqlite_master WHERE type='table' AND name='${this.table}'`;
|
|
1600
|
+
let result = await this.run(sql);
|
|
1601
1601
|
|
|
1602
1602
|
if (result && result.length > 0 && result[0].sql) {
|
|
1603
1603
|
// 在创建表语句中添加 IF NOT EXISTS 条件
|
|
@@ -1627,7 +1627,7 @@ Sql.prototype.backup = async function (file, create = false) {
|
|
|
1627
1627
|
}
|
|
1628
1628
|
|
|
1629
1629
|
// 获取所有数据
|
|
1630
|
-
|
|
1630
|
+
let data = await this.getSql('', '', '*');
|
|
1631
1631
|
|
|
1632
1632
|
if (!data || !Array.isArray(data)) {
|
|
1633
1633
|
throw new Error('获取数据失败');
|
|
@@ -1642,25 +1642,25 @@ Sql.prototype.backup = async function (file, create = false) {
|
|
|
1642
1642
|
|
|
1643
1643
|
// 如果create为true,添加创建表语句
|
|
1644
1644
|
if (create) {
|
|
1645
|
-
|
|
1645
|
+
let create_table_sql = await this._getCreateTableSql();
|
|
1646
1646
|
if (create_table_sql) {
|
|
1647
1647
|
sql_content += create_table_sql + '\n\n';
|
|
1648
1648
|
}
|
|
1649
1649
|
}
|
|
1650
1650
|
|
|
1651
1651
|
// 添加数据插入语句
|
|
1652
|
-
for (
|
|
1653
|
-
|
|
1654
|
-
|
|
1652
|
+
for (let row of data) {
|
|
1653
|
+
let keys = Object.keys(row).map(key => this.escapeId(key)).join(', ');
|
|
1654
|
+
let values = Object.values(row).map(value => this.escape(value)).join(', ');
|
|
1655
1655
|
sql_content += `INSERT INTO \`${this.table}\` (${keys}) VALUES (${values});\n`;
|
|
1656
1656
|
}
|
|
1657
1657
|
|
|
1658
1658
|
// 写入文件(这里需要文件系统模块,实际使用时需要引入 fs)
|
|
1659
|
-
|
|
1660
|
-
|
|
1659
|
+
let fs = require('fs');
|
|
1660
|
+
let path = require('path');
|
|
1661
1661
|
|
|
1662
1662
|
// 确保目录存在
|
|
1663
|
-
|
|
1663
|
+
let dir = path.dirname(file);
|
|
1664
1664
|
if (!fs.existsSync(dir)) {
|
|
1665
1665
|
fs.mkdirSync(dir, { recursive: true });
|
|
1666
1666
|
}
|
|
@@ -1684,20 +1684,20 @@ Sql.prototype.restore = async function (file) {
|
|
|
1684
1684
|
throw new TypeError('表名未设置');
|
|
1685
1685
|
}
|
|
1686
1686
|
|
|
1687
|
-
|
|
1687
|
+
let fs = require('fs');
|
|
1688
1688
|
|
|
1689
1689
|
if (!fs.existsSync(file)) {
|
|
1690
1690
|
throw new Error('备份文件不存在');
|
|
1691
1691
|
}
|
|
1692
1692
|
|
|
1693
1693
|
// 读取 SQL 文件
|
|
1694
|
-
|
|
1694
|
+
let sql_content = fs.readFileSync(file, 'utf8');
|
|
1695
1695
|
|
|
1696
1696
|
// 解析 SQL 语句
|
|
1697
|
-
|
|
1697
|
+
let stmts = this._parseSqlStatements(sql_content);
|
|
1698
1698
|
|
|
1699
1699
|
// 执行每个 SQL 语句
|
|
1700
|
-
for (
|
|
1700
|
+
for (let stmt of stmts) {
|
|
1701
1701
|
if (stmt.trim() && !stmt.startsWith('--')) {
|
|
1702
1702
|
await this.exec(stmt);
|
|
1703
1703
|
}
|
|
@@ -1713,15 +1713,15 @@ Sql.prototype.restore = async function (file) {
|
|
|
1713
1713
|
* @private
|
|
1714
1714
|
*/
|
|
1715
1715
|
Sql.prototype._parseSqlStatements = function (sql) {
|
|
1716
|
-
|
|
1716
|
+
let stmts = [];
|
|
1717
1717
|
let cur_stmt = '';
|
|
1718
1718
|
let in_str = false;
|
|
1719
1719
|
let in_cmt = false;
|
|
1720
1720
|
let quote_char = '';
|
|
1721
1721
|
|
|
1722
1722
|
for (let i = 0; i < sql.length; i++) {
|
|
1723
|
-
|
|
1724
|
-
|
|
1723
|
+
let char = sql[i];
|
|
1724
|
+
let next_char = sql[i + 1] || '';
|
|
1725
1725
|
|
|
1726
1726
|
// 处理字符串
|
|
1727
1727
|
if (!in_cmt && (char === "'" || char === '"') && (i === 0 || sql[i - 1] !== '\\')) {
|
package/test_db/test_basic.db
CHANGED
|
Binary file
|
|
Binary file
|