mm_mysql 2.2.0 → 2.2.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/README.md +100 -34
- package/db.js +144 -170
- package/index.js +393 -156
- package/package.json +2 -2
- package/sql.js +190 -349
- package/test.js +218 -128
- package/test_create_table.js +0 -193
package/sql.js
CHANGED
|
@@ -3,23 +3,24 @@
|
|
|
3
3
|
* @author <a href="http://qww.elins.cn">邱文武</a>
|
|
4
4
|
* @version 1.2
|
|
5
5
|
*/
|
|
6
|
-
require('mm_logs');
|
|
7
6
|
const {
|
|
8
7
|
escape,
|
|
9
8
|
escapeId
|
|
10
9
|
} = require('mysql2');
|
|
10
|
+
const { Base } = require('mm_expand');
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @class 数据库语法通用类
|
|
14
14
|
* @property {Function} filter 设置并过滤参数
|
|
15
15
|
*/
|
|
16
|
-
class Sql {
|
|
16
|
+
class Sql extends Base {
|
|
17
17
|
/**
|
|
18
18
|
* 数据库管理器
|
|
19
19
|
* @param {Function} run 查询函数
|
|
20
20
|
* @param {Function} exec 更改函数
|
|
21
21
|
*/
|
|
22
22
|
constructor(run, exec) {
|
|
23
|
+
super();
|
|
23
24
|
/**
|
|
24
25
|
* 查询函数
|
|
25
26
|
*/
|
|
@@ -428,18 +429,18 @@ Sql.prototype.toWhere = function (obj, like) {
|
|
|
428
429
|
val = val.trim("'");
|
|
429
430
|
}
|
|
430
431
|
val = escape(val);
|
|
431
|
-
if (k.
|
|
432
|
+
if (k.endsWith('_min')) {
|
|
432
433
|
where += " and " + escapeId(k.replace('_min', "")) + " >= " + val;
|
|
433
|
-
} else if (k.
|
|
434
|
+
} else if (k.endsWith('_max')) {
|
|
434
435
|
where += " and " + escapeId(k.replace('_max', "")) + " <= " + val;
|
|
435
|
-
} else if (k.
|
|
436
|
+
} else if (k.endsWith('_not')) {
|
|
436
437
|
where += " and " + escapeId(k.replace('_not', "")) + " != " + val;
|
|
437
|
-
} else if (k.
|
|
438
|
+
} else if (k.endsWith('_has')) {
|
|
438
439
|
var vals = val.trim("'").split(',').map((o) => {
|
|
439
440
|
return "'" + o + "'"
|
|
440
441
|
});
|
|
441
442
|
where += " and " + escapeId(k.replace('_has', "")) + " in (" + vals.join(',') + ")";
|
|
442
|
-
} else if (k.
|
|
443
|
+
} else if (k.endsWith('_like')) {
|
|
443
444
|
where += " and " + escapeId(k.replace('_like', "")) + " LIKE '%" + val.trim("'") + "%'";
|
|
444
445
|
} else if (typeof (val) === "string" && !/^[0-9]+$/.test(val)) {
|
|
445
446
|
where += " and " + escapeId(k) + " LIKE '%" + val.trim("'") + "%'";
|
|
@@ -454,18 +455,18 @@ Sql.prototype.toWhere = function (obj, like) {
|
|
|
454
455
|
val = val.trim("'");
|
|
455
456
|
}
|
|
456
457
|
val = escape(val);
|
|
457
|
-
if (k.
|
|
458
|
+
if (k.endsWith('_min')) {
|
|
458
459
|
where += " and " + escapeId(k.replace('_min', "")) + " >= " + val;
|
|
459
|
-
} else if (k.
|
|
460
|
+
} else if (k.endsWith('_max')) {
|
|
460
461
|
where += " and " + escapeId(k.replace('_max', "")) + " <= " + val;
|
|
461
|
-
} else if (k.
|
|
462
|
+
} else if (k.endsWith('_not')) {
|
|
462
463
|
where += " and " + escapeId(k.replace('_not', "")) + " != " + val;
|
|
463
|
-
} else if (k.
|
|
464
|
+
} else if (k.endsWith('_has')) {
|
|
464
465
|
var vals = val.trim("'").split(',').map((o) => {
|
|
465
466
|
return "'" + o + "'"
|
|
466
467
|
});
|
|
467
468
|
where += " and " + escapeId(k.replace('_has', "")) + " in (" + vals.join(',') + ")";
|
|
468
|
-
} else if (k.
|
|
469
|
+
} else if (k.endsWith('_like')) {
|
|
469
470
|
where += " and " + escapeId(k.replace('_like', "")) + " LIKE '%" + val.trim("'") + "%'";
|
|
470
471
|
} else {
|
|
471
472
|
where += " and " + escapeId(k) + " = " + val;
|
|
@@ -493,10 +494,10 @@ Sql.prototype.toSet = function (obj) {
|
|
|
493
494
|
}
|
|
494
495
|
val = escape(val);
|
|
495
496
|
|
|
496
|
-
if (k.
|
|
497
|
+
if (k.endsWith('_add')) {
|
|
497
498
|
const k2 = escapeId(k.replace('_add', ""));
|
|
498
499
|
set += "," + k2 + " = " + k2 + " + " + val;
|
|
499
|
-
} else if (k.
|
|
500
|
+
} else if (k.endsWith('_del')) {
|
|
500
501
|
const k3 = escapeId(k.replace('_del', ""));
|
|
501
502
|
set += "," + k3 + " = " + k3 + " - " + val;
|
|
502
503
|
} else {
|
|
@@ -600,26 +601,14 @@ Sql.prototype.add = async function (body) {
|
|
|
600
601
|
throw new Error('表名或数据未设置');
|
|
601
602
|
}
|
|
602
603
|
try {
|
|
603
|
-
// 触发前置事件
|
|
604
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function') {
|
|
605
|
-
await $.eventer.run("mysql_add_before:" + this.table, { body });
|
|
606
|
-
}
|
|
607
|
-
|
|
608
604
|
const sql = this.toAddSql(body);
|
|
609
605
|
this.sql = sql;
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
// 触发后置事件
|
|
613
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function') {
|
|
614
|
-
await $.eventer.run("mysql_add_after:" + this.table, { body, sql: this.sql, error: this.error, bl });
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
return bl;
|
|
606
|
+
return await this.exec(sql);
|
|
618
607
|
} catch (err) {
|
|
619
608
|
this.error = err.message;
|
|
620
|
-
|
|
621
|
-
throw err;
|
|
609
|
+
this.logger('error', '添加数据失败', err);
|
|
622
610
|
}
|
|
611
|
+
return 0;
|
|
623
612
|
};
|
|
624
613
|
|
|
625
614
|
/**
|
|
@@ -633,26 +622,15 @@ Sql.prototype.del = async function (query, like) {
|
|
|
633
622
|
throw new Error('表名未设置');
|
|
634
623
|
}
|
|
635
624
|
try {
|
|
636
|
-
// 触发前置事件
|
|
637
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function') {
|
|
638
|
-
await $.eventer.run("mysql_del_before:" + this.table, { query, like });
|
|
639
|
-
}
|
|
640
|
-
|
|
641
625
|
const sql = this.toDelSql(query, like);
|
|
642
626
|
this.sql = sql;
|
|
643
627
|
const bl = await this.exec(sql);
|
|
644
|
-
|
|
645
|
-
// 触发后置事件
|
|
646
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function') {
|
|
647
|
-
await $.eventer.run("mysql_del_after:" + this.table, { query, like, sql: this.sql, error: this.error, bl });
|
|
648
|
-
}
|
|
649
|
-
|
|
650
628
|
return bl;
|
|
651
629
|
} catch (err) {
|
|
652
630
|
this.error = err.message;
|
|
653
|
-
|
|
654
|
-
throw err;
|
|
631
|
+
this.logger('error', '删除数据失败', err);
|
|
655
632
|
}
|
|
633
|
+
return 0;
|
|
656
634
|
};
|
|
657
635
|
|
|
658
636
|
/**
|
|
@@ -667,26 +645,15 @@ Sql.prototype.set = async function (query, body, like) {
|
|
|
667
645
|
throw new Error('表名或数据未设置');
|
|
668
646
|
}
|
|
669
647
|
try {
|
|
670
|
-
// 触发前置事件
|
|
671
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function') {
|
|
672
|
-
await $.eventer.run("mysql_set_before:" + this.table, { query, body, like, page: this.page, size: this.size });
|
|
673
|
-
}
|
|
674
|
-
|
|
675
648
|
const sql = this.toSetSql(query, body, like);
|
|
676
649
|
this.sql = sql;
|
|
677
650
|
const bl = await this.exec(sql);
|
|
678
|
-
|
|
679
|
-
// 触发后置事件
|
|
680
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function') {
|
|
681
|
-
await $.eventer.run("mysql_set_after:" + this.table, { query, body, like, page: this.page, size: this.size, sql: this.sql, error: this.error, bl });
|
|
682
|
-
}
|
|
683
|
-
|
|
684
651
|
return bl;
|
|
685
652
|
} catch (err) {
|
|
686
653
|
this.error = err.message;
|
|
687
|
-
|
|
688
|
-
throw err;
|
|
654
|
+
this.logger('error', '修改数据失败', err);
|
|
689
655
|
}
|
|
656
|
+
return 0;
|
|
690
657
|
};
|
|
691
658
|
|
|
692
659
|
/**
|
|
@@ -727,11 +694,6 @@ Sql.prototype.addOrSetSql = async function (where, set, like) {
|
|
|
727
694
|
}
|
|
728
695
|
}
|
|
729
696
|
} else {
|
|
730
|
-
// 触发前置事件
|
|
731
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function' && typeof body === "object") {
|
|
732
|
-
await $.eventer.run("mysql_add_before:" + this.table, { body });
|
|
733
|
-
}
|
|
734
|
-
|
|
735
697
|
for (const k in set) {
|
|
736
698
|
if (!Object.prototype.hasOwnProperty.call(set, k)) continue;
|
|
737
699
|
|
|
@@ -746,36 +708,21 @@ Sql.prototype.addOrSetSql = async function (where, set, like) {
|
|
|
746
708
|
|
|
747
709
|
const bl = await this.addSql(key.replace(",", ""), value.replace(",", ""));
|
|
748
710
|
|
|
749
|
-
// 触发后置事件
|
|
750
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function' && typeof body === "object") {
|
|
751
|
-
await $.eventer.run("mysql_add_after:" + this.table, { body, sql: this.sql, error: this.error, bl });
|
|
752
|
-
}
|
|
753
|
-
|
|
754
711
|
return bl;
|
|
755
712
|
} else {
|
|
756
|
-
// 触发前置事件
|
|
757
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function' && typeof set === "object") {
|
|
758
|
-
await $.eventer.run("mysql_set_before:" + this.table, { query, body, like, page: this.page, size: this.size, sql: this.sql });
|
|
759
|
-
}
|
|
760
|
-
|
|
761
713
|
if (typeof set === "object") {
|
|
762
714
|
set = await this.toSet(set);
|
|
763
715
|
}
|
|
764
716
|
|
|
765
717
|
const bl1 = await this.setSql(whereStr, set);
|
|
766
718
|
|
|
767
|
-
// 触发后置事件
|
|
768
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function' && typeof body === "object") {
|
|
769
|
-
await $.eventer.run("mysql_set_after:" + this.table, { query, body, like, page: this.page, size: this.size, sql: this.sql, error: this.error, bl: bl1 });
|
|
770
|
-
}
|
|
771
|
-
|
|
772
719
|
return bl1;
|
|
773
720
|
}
|
|
774
721
|
} catch (err) {
|
|
775
722
|
this.error = err.message;
|
|
776
|
-
|
|
777
|
-
throw err;
|
|
723
|
+
this.logger('error', '添加或修改数据失败', err);
|
|
778
724
|
}
|
|
725
|
+
return 0;
|
|
779
726
|
};
|
|
780
727
|
|
|
781
728
|
/**
|
|
@@ -801,63 +748,19 @@ Sql.prototype.get = async function (query, sort, view, like, timeout = 60000) {
|
|
|
801
748
|
// 使用Promise.race实现超时控制
|
|
802
749
|
return await Promise.race([
|
|
803
750
|
(async () => {
|
|
804
|
-
// 安全触发事件,避免事件系统问题影响核心功能
|
|
805
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function') {
|
|
806
|
-
try {
|
|
807
|
-
// 添加超时保护的事件触发
|
|
808
|
-
await Promise.race([
|
|
809
|
-
$.eventer.run("mysql_get_before:" + this.table, {
|
|
810
|
-
query,
|
|
811
|
-
sort,
|
|
812
|
-
view,
|
|
813
|
-
like,
|
|
814
|
-
page: this.page,
|
|
815
|
-
size: this.size
|
|
816
|
-
}),
|
|
817
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('事件处理超时')), 5000))
|
|
818
|
-
]);
|
|
819
|
-
} catch (eventError) {
|
|
820
|
-
$.log.warn(`事件处理失败,但不影响查询: ${eventError.message}`);
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
|
|
824
751
|
// 生成SQL并执行
|
|
825
752
|
const sql = this.toGetSql(query, sort, view, like);
|
|
826
753
|
this.sql = sql;
|
|
827
754
|
const list = await this.run(sql);
|
|
828
|
-
|
|
829
|
-
// 安全触发后置事件
|
|
830
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function') {
|
|
831
|
-
try {
|
|
832
|
-
// 添加超时保护的事件触发
|
|
833
|
-
await Promise.race([
|
|
834
|
-
$.eventer.run("mysql_get_after:" + this.table, {
|
|
835
|
-
query,
|
|
836
|
-
sort,
|
|
837
|
-
view,
|
|
838
|
-
like,
|
|
839
|
-
page: this.page,
|
|
840
|
-
size: this.size,
|
|
841
|
-
sql: this.sql,
|
|
842
|
-
error: this.error,
|
|
843
|
-
list
|
|
844
|
-
}),
|
|
845
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('事件处理超时')), 5000))
|
|
846
|
-
]);
|
|
847
|
-
} catch (eventError) {
|
|
848
|
-
$.log.warn(`事件处理失败,但不影响查询返回: ${eventError.message}`);
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
|
|
852
755
|
return list;
|
|
853
756
|
})(),
|
|
854
757
|
timeoutPromise
|
|
855
758
|
]);
|
|
856
759
|
} catch (err) {
|
|
857
760
|
this.error = err.message;
|
|
858
|
-
|
|
859
|
-
throw err;
|
|
761
|
+
this.logger('error', '查询数据失败', err);
|
|
860
762
|
}
|
|
763
|
+
return [];
|
|
861
764
|
};
|
|
862
765
|
|
|
863
766
|
/**
|
|
@@ -897,9 +800,9 @@ Sql.prototype.getObj = async function (query, sort, view, like, timeout = 60000)
|
|
|
897
800
|
return obj;
|
|
898
801
|
} catch (err) {
|
|
899
802
|
this.error = err.message;
|
|
900
|
-
|
|
901
|
-
throw err;
|
|
803
|
+
this.logger('error', '查询单条数据失败', err);
|
|
902
804
|
}
|
|
805
|
+
return null;
|
|
903
806
|
};
|
|
904
807
|
|
|
905
808
|
/**
|
|
@@ -922,52 +825,21 @@ Sql.prototype.count = async function (query, like, timeout = 60000) {
|
|
|
922
825
|
|
|
923
826
|
return await Promise.race([
|
|
924
827
|
(async () => {
|
|
925
|
-
// 安全触发事件
|
|
926
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function') {
|
|
927
|
-
try {
|
|
928
|
-
await Promise.race([
|
|
929
|
-
$.eventer.run("mysql_count_before:" + this.table, { query, like }),
|
|
930
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('事件处理超时')), 5000))
|
|
931
|
-
]);
|
|
932
|
-
} catch (eventError) {
|
|
933
|
-
$.log.warn(`事件处理失败,但不影响统计: ${eventError.message}`);
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
|
|
937
828
|
// 正确生成count SQL
|
|
938
829
|
const where = typeof query === 'string' ? query : await this.toWhere(query, like);
|
|
939
830
|
const sql = "SELECT COUNT(*) as num FROM `" + this.table + "`" + (where ? " WHERE " + where : "");
|
|
940
831
|
this.sql = sql;
|
|
941
832
|
const list = await this.run(sql);
|
|
942
833
|
const total = list && list[0] && list[0].num ? parseInt(list[0].num) : 0;
|
|
943
|
-
|
|
944
|
-
// 安全触发事件
|
|
945
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function') {
|
|
946
|
-
try {
|
|
947
|
-
await Promise.race([
|
|
948
|
-
$.eventer.run("mysql_count_after:" + this.table, {
|
|
949
|
-
query,
|
|
950
|
-
like,
|
|
951
|
-
sql: this.sql,
|
|
952
|
-
error: this.error,
|
|
953
|
-
total
|
|
954
|
-
}),
|
|
955
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('事件处理超时')), 5000))
|
|
956
|
-
]);
|
|
957
|
-
} catch (eventError) {
|
|
958
|
-
$.log.warn(`事件处理失败,但不影响统计返回: ${eventError.message}`);
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
|
|
962
834
|
return total;
|
|
963
835
|
})(),
|
|
964
836
|
timeoutPromise
|
|
965
837
|
]);
|
|
966
838
|
} catch (err) {
|
|
967
839
|
this.error = err.message;
|
|
968
|
-
|
|
969
|
-
throw err;
|
|
840
|
+
this.logger('error', '统计数据失败', err);
|
|
970
841
|
}
|
|
842
|
+
return 0;
|
|
971
843
|
};
|
|
972
844
|
|
|
973
845
|
/**
|
|
@@ -1011,13 +883,13 @@ Sql.prototype.addList = async function (list, lock = true, batchSize = 100, time
|
|
|
1011
883
|
|
|
1012
884
|
// 分批处理大数据量
|
|
1013
885
|
const totalBatches = Math.ceil(list.length / batchSize);
|
|
1014
|
-
|
|
886
|
+
this.logger('info', `开始分批添加数据,共${totalBatches}批,每批${batchSize}条`);
|
|
1015
887
|
|
|
1016
888
|
// 分批执行,每批一个单独的批量插入语句
|
|
1017
889
|
let finalResult = null;
|
|
1018
890
|
for (let i = 0; i < totalBatches; i++) {
|
|
1019
891
|
const batch = list.slice(i * batchSize, (i + 1) * batchSize);
|
|
1020
|
-
|
|
892
|
+
this.logger('debug', `处理第${i + 1}/${totalBatches}批数据,${batch.length}条`);
|
|
1021
893
|
|
|
1022
894
|
// 生成批量插入SQL
|
|
1023
895
|
const batchSql = this.toBatchAddSql(batch);
|
|
@@ -1032,19 +904,15 @@ Sql.prototype.addList = async function (list, lock = true, batchSize = 100, time
|
|
|
1032
904
|
]);
|
|
1033
905
|
}
|
|
1034
906
|
|
|
1035
|
-
|
|
907
|
+
this.logger('info', `批量添加数据完成,共${list.length}条`);
|
|
1036
908
|
return finalResult;
|
|
1037
909
|
})(),
|
|
1038
910
|
timeoutPromise
|
|
1039
911
|
]);
|
|
1040
912
|
} catch (error) {
|
|
1041
|
-
|
|
1042
|
-
error: error.message,
|
|
1043
|
-
table: this.table,
|
|
1044
|
-
list_length: list.length
|
|
1045
|
-
});
|
|
1046
|
-
throw error;
|
|
913
|
+
this.logger('error', '批量添加数据失败', error);
|
|
1047
914
|
}
|
|
915
|
+
return 0;
|
|
1048
916
|
};
|
|
1049
917
|
|
|
1050
918
|
/**
|
|
@@ -1125,7 +993,7 @@ Sql.prototype.delList = async function (list, like, batchSize = 100, timeout = 6
|
|
|
1125
993
|
|
|
1126
994
|
// 分批处理大数据量
|
|
1127
995
|
const totalBatches = Math.ceil(list.length / batchSize);
|
|
1128
|
-
|
|
996
|
+
this.logger('info', `开始分批删除数据,共${totalBatches}批,每批${batchSize}条`);
|
|
1129
997
|
|
|
1130
998
|
// 使用事务包装整个操作以保证原子性
|
|
1131
999
|
let finalResult = null;
|
|
@@ -1136,7 +1004,7 @@ Sql.prototype.delList = async function (list, like, batchSize = 100, timeout = 6
|
|
|
1136
1004
|
// 分批处理
|
|
1137
1005
|
for (let i = 0; i < totalBatches; i++) {
|
|
1138
1006
|
const batch = list.slice(i * batchSize, (i + 1) * batchSize);
|
|
1139
|
-
|
|
1007
|
+
this.logger('debug', `处理第${i + 1}/${totalBatches}批数据,${batch.length}条`);
|
|
1140
1008
|
|
|
1141
1009
|
let batchSql = "";
|
|
1142
1010
|
for (const item of batch) {
|
|
@@ -1158,23 +1026,22 @@ Sql.prototype.delList = async function (list, like, batchSize = 100, timeout = 6
|
|
|
1158
1026
|
// 发生错误时回滚事务
|
|
1159
1027
|
try {
|
|
1160
1028
|
await this.exec("ROLLBACK;", 15000);
|
|
1161
|
-
|
|
1029
|
+
this.logger('error', '批量删除数据失败,事务已回滚', error);
|
|
1162
1030
|
} catch (rollbackError) {
|
|
1163
|
-
|
|
1031
|
+
this.logger('error', '批量删除数据失败,事务回滚也失败', rollbackError);
|
|
1164
1032
|
}
|
|
1165
|
-
throw error;
|
|
1166
1033
|
}
|
|
1167
1034
|
|
|
1168
|
-
|
|
1035
|
+
this.logger('info', `批量删除数据完成,共${list.length}条`);
|
|
1169
1036
|
return finalResult;
|
|
1170
1037
|
})(),
|
|
1171
1038
|
timeoutPromise
|
|
1172
1039
|
]);
|
|
1173
1040
|
} catch (err) {
|
|
1174
1041
|
this.error = err.message;
|
|
1175
|
-
|
|
1176
|
-
throw err;
|
|
1042
|
+
this.logger('error', '批量删除数据失败', err);
|
|
1177
1043
|
}
|
|
1044
|
+
return 0;
|
|
1178
1045
|
};
|
|
1179
1046
|
|
|
1180
1047
|
/**
|
|
@@ -1199,14 +1066,14 @@ Sql.prototype.setList = async function (list, like = false, batchSize = 100, tim
|
|
|
1199
1066
|
(async () => {
|
|
1200
1067
|
// 分批处理大数据量
|
|
1201
1068
|
const totalBatches = Math.ceil(list.length / batchSize);
|
|
1202
|
-
|
|
1069
|
+
this.logger('info', `开始分批修改数据,共${totalBatches}批,每批${batchSize}条`);
|
|
1203
1070
|
|
|
1204
1071
|
let finalResult = null;
|
|
1205
1072
|
|
|
1206
1073
|
// 逐条处理记录,保持简单可靠
|
|
1207
1074
|
for (let i = 0; i < list.length; i++) {
|
|
1208
1075
|
const item = list[i];
|
|
1209
|
-
|
|
1076
|
+
this.logger('debug', `处理第${i + 1}/${list.length}条记录`);
|
|
1210
1077
|
|
|
1211
1078
|
// 生成单个更新SQL
|
|
1212
1079
|
const sql = this.toSetSql(item.query, item.item, like);
|
|
@@ -1227,9 +1094,9 @@ Sql.prototype.setList = async function (list, like = false, batchSize = 100, tim
|
|
|
1227
1094
|
]);
|
|
1228
1095
|
} catch (error) {
|
|
1229
1096
|
this.error = error.message;
|
|
1230
|
-
|
|
1231
|
-
throw error;
|
|
1097
|
+
this.logger('error', '批量修改数据失败', error);
|
|
1232
1098
|
}
|
|
1099
|
+
return 0;
|
|
1233
1100
|
};
|
|
1234
1101
|
|
|
1235
1102
|
/* 辅助类 */
|
|
@@ -1429,72 +1296,65 @@ Sql.prototype.tplBody = function (paramDt, sqlDt) {
|
|
|
1429
1296
|
* @returns {Promise<boolean>} 是否加载成功
|
|
1430
1297
|
*/
|
|
1431
1298
|
Sql.prototype.load = async function (file) {
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
error: error.message,
|
|
1492
|
-
file: file
|
|
1493
|
-
});
|
|
1494
|
-
|
|
1495
|
-
// 抛出错误
|
|
1496
|
-
throw error;
|
|
1497
|
-
}
|
|
1299
|
+
try {
|
|
1300
|
+
// 记录操作日志
|
|
1301
|
+
if (this.config && this.config.debug) {
|
|
1302
|
+
this.logger('debug', `开始从文件加载数据库`, {
|
|
1303
|
+
file: file
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
// 检查文件是否存在
|
|
1308
|
+
if (!file.hasFile()) {
|
|
1309
|
+
throw new Error(`SQL文件不存在: ${file}`);
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
// 读取SQL文件内容
|
|
1313
|
+
const sqlContent = await $.file.readText(file);
|
|
1314
|
+
|
|
1315
|
+
if (!sqlContent || sqlContent.trim() === '') {
|
|
1316
|
+
throw new Error(`SQL文件内容为空: ${file}`);
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
// 分割SQL语句(按分号分割,但需要注意处理字符串中的分号)
|
|
1320
|
+
const sqlStatements = this._splitSqlStatements(sqlContent);
|
|
1321
|
+
|
|
1322
|
+
// 开始事务执行SQL语句
|
|
1323
|
+
await this.exec('START TRANSACTION');
|
|
1324
|
+
|
|
1325
|
+
try {
|
|
1326
|
+
// 逐个执行SQL语句
|
|
1327
|
+
for (const sql of sqlStatements) {
|
|
1328
|
+
const trimmedSql = sql.trim();
|
|
1329
|
+
if (trimmedSql) {
|
|
1330
|
+
await this.exec(trimmedSql);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
// 提交事务
|
|
1335
|
+
await this.exec('COMMIT');
|
|
1336
|
+
|
|
1337
|
+
if (this.config && this.config.debug) {
|
|
1338
|
+
this.logger('info', `数据库加载成功`, {
|
|
1339
|
+
file: file,
|
|
1340
|
+
statementCount: sqlStatements.length
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
return true;
|
|
1345
|
+
} catch (err) {
|
|
1346
|
+
// 回滚事务
|
|
1347
|
+
await this.exec('ROLLBACK').catch(rollbackErr => {
|
|
1348
|
+
this.logger('error', '事务回滚失败', rollbackErr);
|
|
1349
|
+
});
|
|
1350
|
+
|
|
1351
|
+
this.logger('error', '数据库加载失败', err);
|
|
1352
|
+
}
|
|
1353
|
+
} catch (error) {
|
|
1354
|
+
// 记录错误日志
|
|
1355
|
+
this.logger('error', '数据库加载失败', error);
|
|
1356
|
+
}
|
|
1357
|
+
return false;
|
|
1498
1358
|
};
|
|
1499
1359
|
|
|
1500
1360
|
/**
|
|
@@ -1503,84 +1363,84 @@ Sql.prototype.load = async function (file) {
|
|
|
1503
1363
|
* @param {String} sqlContent - SQL内容
|
|
1504
1364
|
* @returns {Array} SQL语句数组
|
|
1505
1365
|
*/
|
|
1506
|
-
Sql.prototype._splitSqlStatements = function(sqlContent) {
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1366
|
+
Sql.prototype._splitSqlStatements = function (sqlContent) {
|
|
1367
|
+
const statements = [];
|
|
1368
|
+
let inString = false;
|
|
1369
|
+
let stringChar = '';
|
|
1370
|
+
let inComment = false;
|
|
1371
|
+
let currentStatement = '';
|
|
1372
|
+
|
|
1373
|
+
for (let i = 0; i < sqlContent.length; i++) {
|
|
1374
|
+
const char = sqlContent[i];
|
|
1375
|
+
const nextChar = i + 1 < sqlContent.length ? sqlContent[i + 1] : '';
|
|
1376
|
+
|
|
1377
|
+
// 处理注释
|
|
1378
|
+
if (!inString && !inComment && char === '-' && nextChar === '-') {
|
|
1379
|
+
inComment = true;
|
|
1380
|
+
i++; // 跳过第二个'-'
|
|
1381
|
+
continue;
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
if (inComment && char === '\n') {
|
|
1385
|
+
inComment = false;
|
|
1386
|
+
continue;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
if (inComment) {
|
|
1390
|
+
continue;
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
// 处理多行注释
|
|
1394
|
+
if (!inString && !inComment && char === '/' && nextChar === '*') {
|
|
1395
|
+
inComment = true;
|
|
1396
|
+
i++; // 跳过'*'
|
|
1397
|
+
continue;
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
if (inComment && char === '*' && nextChar === '/') {
|
|
1401
|
+
inComment = false;
|
|
1402
|
+
i++; // 跳过'/'
|
|
1403
|
+
continue;
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
// 处理字符串
|
|
1407
|
+
if (!inComment && (char === "'" || char === '"') && (!inString || stringChar === char)) {
|
|
1408
|
+
// 检查是否是转义的引号
|
|
1409
|
+
let escaped = false;
|
|
1410
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
1411
|
+
if (sqlContent[j] === '\\') {
|
|
1412
|
+
escaped = !escaped;
|
|
1413
|
+
} else {
|
|
1414
|
+
break;
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
if (!escaped) {
|
|
1419
|
+
if (inString && stringChar === char) {
|
|
1420
|
+
inString = false;
|
|
1421
|
+
stringChar = '';
|
|
1422
|
+
} else if (!inString) {
|
|
1423
|
+
inString = true;
|
|
1424
|
+
stringChar = char;
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
// 分割语句
|
|
1430
|
+
if (!inString && !inComment && char === ';') {
|
|
1431
|
+
statements.push(currentStatement.trim());
|
|
1432
|
+
currentStatement = '';
|
|
1433
|
+
} else {
|
|
1434
|
+
currentStatement += char;
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
// 添加最后一个语句(如果有)
|
|
1439
|
+
if (currentStatement.trim()) {
|
|
1440
|
+
statements.push(currentStatement.trim());
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
return statements;
|
|
1584
1444
|
};
|
|
1585
1445
|
|
|
1586
1446
|
/**
|
|
@@ -1614,7 +1474,7 @@ Sql.prototype.model = function (model) {
|
|
|
1614
1474
|
const set = {};
|
|
1615
1475
|
set[prop] = value;
|
|
1616
1476
|
_this.set(query, set, false).catch(err => {
|
|
1617
|
-
|
|
1477
|
+
this.logger('error', '模型数据更新失败', err);
|
|
1618
1478
|
});
|
|
1619
1479
|
}
|
|
1620
1480
|
}
|
|
@@ -1631,7 +1491,7 @@ Sql.prototype.model = function (model) {
|
|
|
1631
1491
|
* @param {Boolean} like 是否使用like匹配, 为空使用默认方式
|
|
1632
1492
|
* @return {Promise<Object>} 执行结果
|
|
1633
1493
|
*/
|
|
1634
|
-
Sql.prototype.addOrSet = async function(where, set, like) {
|
|
1494
|
+
Sql.prototype.addOrSet = async function (where, set, like) {
|
|
1635
1495
|
if (!this.table || !where || !set) {
|
|
1636
1496
|
throw new Error('表名、条件或数据未设置');
|
|
1637
1497
|
}
|
|
@@ -1662,11 +1522,6 @@ Sql.prototype.addOrSet = async function(where, set, like) {
|
|
|
1662
1522
|
}
|
|
1663
1523
|
}
|
|
1664
1524
|
} else {
|
|
1665
|
-
// 触发前置事件
|
|
1666
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function' && typeof body === "object") {
|
|
1667
|
-
await $.eventer.run("mysql_add_before:" + this.table, { body });
|
|
1668
|
-
}
|
|
1669
|
-
|
|
1670
1525
|
for (const k in set) {
|
|
1671
1526
|
if (!Object.prototype.hasOwnProperty.call(set, k)) continue;
|
|
1672
1527
|
|
|
@@ -1680,37 +1535,23 @@ Sql.prototype.addOrSet = async function(where, set, like) {
|
|
|
1680
1535
|
}
|
|
1681
1536
|
|
|
1682
1537
|
const bl = await this.addSql(key.replace(",", ""), value.replace(",", ""));
|
|
1683
|
-
|
|
1684
|
-
// 触发后置事件
|
|
1685
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function' && typeof body === "object") {
|
|
1686
|
-
await $.eventer.run("mysql_add_after:" + this.table, { body, sql: this.sql, error: this.error, bl });
|
|
1687
|
-
}
|
|
1688
|
-
|
|
1689
1538
|
return bl;
|
|
1690
1539
|
} else {
|
|
1691
|
-
// 触发前置事件
|
|
1692
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function' && typeof set === "object") {
|
|
1693
|
-
await $.eventer.run("mysql_set_before:" + this.table, { query, body, like, page: this.page, size: this.size, sql: this.sql });
|
|
1694
|
-
}
|
|
1695
|
-
|
|
1696
1540
|
if (typeof set === "object") {
|
|
1697
1541
|
set = await this.toSet(set);
|
|
1698
1542
|
}
|
|
1699
1543
|
|
|
1700
1544
|
const bl1 = await this.setSql(whereStr, set);
|
|
1701
1545
|
|
|
1702
|
-
// 触发后置事件
|
|
1703
|
-
if (typeof $.eventer === 'object' && typeof $.eventer.run === 'function' && typeof body === "object") {
|
|
1704
|
-
await $.eventer.run("mysql_set_after:" + this.table, { query, body, like, page: this.page, size: this.size, sql: this.sql, error: this.error, bl: bl1 });
|
|
1705
|
-
}
|
|
1706
|
-
|
|
1707
1546
|
return bl1;
|
|
1708
1547
|
}
|
|
1709
1548
|
} catch (err) {
|
|
1710
1549
|
this.error = err.message;
|
|
1711
|
-
|
|
1712
|
-
throw err;
|
|
1550
|
+
this.logger('error', '添加或修改数据失败', err);
|
|
1713
1551
|
}
|
|
1552
|
+
return 0;
|
|
1714
1553
|
};
|
|
1715
1554
|
|
|
1716
|
-
module.exports =
|
|
1555
|
+
module.exports = {
|
|
1556
|
+
Sql
|
|
1557
|
+
};
|