mm_sqlite 1.4.0 → 1.4.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/db.js CHANGED
@@ -75,21 +75,15 @@ DB.prototype.new = function (table = '', key = '') {
75
75
  * @returns {Promise<object>} 数据库连接对象
76
76
  */
77
77
  DB.prototype.getConn = async function (timeout = 15000) {
78
- try {
79
- // 直接使用SQLite实例的getConn方法,避免Promise.race导致的死锁
80
- return await this.getParent().getConn(timeout);
81
- } catch (error) {
82
- this.log('error', '获取连接失败', error);
83
- // 重新抛出异常,因为调用方需要连接对象
84
- throw error;
85
- }
78
+ // 直接使用SQLite实例的getConn方法,避免Promise.race导致的死锁
79
+ return await this.getParent().getConn(timeout);
86
80
  };
87
81
 
88
82
  /**
89
83
  * 开始事务
90
84
  * @returns {Promise<object>}
91
85
  */
92
- DB.prototype.start = async function() {
86
+ DB.prototype.start = async function () {
93
87
  this.task = 1;
94
88
  try {
95
89
  await this.exec('BEGIN;');
@@ -116,17 +110,17 @@ DB.prototype.start = async function() {
116
110
  * @returns {Promise<void>}
117
111
  * @throws {TypeError} 当transaction参数无效时
118
112
  */
119
- DB.prototype.commit = async function(transaction) {
113
+ DB.prototype.commit = async function (transaction) {
120
114
  // 参数校验
121
115
  if (!transaction || typeof transaction !== 'object') {
122
116
  throw new TypeError('transaction must be object');
123
117
  }
124
-
118
+
125
119
  if (this.task !== 1) {
126
120
  this.log('warn', '没有活跃的事务可提交');
127
121
  return;
128
122
  }
129
-
123
+
130
124
  try {
131
125
  await this.exec('COMMIT;', [], 15000);
132
126
  this.task = 0;
@@ -158,17 +152,17 @@ DB.prototype.end = function () {
158
152
  * @returns {Promise<void>}
159
153
  * @throws {TypeError} 当transaction参数无效时
160
154
  */
161
- DB.prototype.back = async function(transaction) {
155
+ DB.prototype.back = async function (transaction) {
162
156
  // 参数校验
163
157
  if (!transaction || typeof transaction !== 'object') {
164
158
  throw new TypeError('transaction must be object');
165
159
  }
166
-
160
+
167
161
  if (this.task !== 1) {
168
162
  this.log('warn', '没有活跃的事务可回滚');
169
163
  return;
170
164
  }
171
-
165
+
172
166
  try {
173
167
  await this.exec('ROLLBACK;', [], 15000);
174
168
  this.task = 0;
@@ -186,22 +180,22 @@ DB.prototype.back = async function(transaction) {
186
180
  * @returns {Promise<*>}
187
181
  * @throws {TypeError} 当callback参数无效时
188
182
  */
189
- DB.prototype.transaction = async function(callback) {
183
+ DB.prototype.transaction = async function (callback) {
190
184
  // 参数校验
191
185
  if (typeof callback !== 'function') {
192
186
  throw new TypeError('callback must be function');
193
187
  }
194
-
188
+
195
189
  try {
196
190
  // 开始事务
197
191
  await this.start();
198
-
192
+
199
193
  // 执行回调函数
200
194
  const result = await callback();
201
-
195
+
202
196
  // 提交事务
203
197
  await this.commit({});
204
-
198
+
205
199
  return result;
206
200
  } catch (err) {
207
201
  // 回滚事务
@@ -219,25 +213,20 @@ DB.prototype.transaction = async function(callback) {
219
213
  * @returns {Promise|Array} 表名数组
220
214
  */
221
215
  DB.prototype.tables = async function (table, timeout = 15000) {
222
- try {
223
- const list = await this.run("SELECT `name` FROM sqlite_master WHERE type='table';", [], timeout);
224
- if (table) {
225
- // 简单的过滤实现
226
- const filtered = [];
227
- for (const item of list) {
228
- const value = item.name;
229
- if (value && value.includes(table)) {
230
- filtered.push(item);
231
- }
216
+ const list = await this.run("SELECT `name` FROM sqlite_master WHERE type='table';", [], timeout);
217
+ if (table) {
218
+ // 简单的过滤实现
219
+ const filtered = [];
220
+ for (const item of list) {
221
+ const value = item.name;
222
+ if (value && value.includes(table)) {
223
+ filtered.push(item);
232
224
  }
233
- return filtered.map(item => item.name);
234
225
  }
235
- // 使用原生方法提取表名
236
- return list.map(item => item.name);
237
- } catch (err) {
238
- this.log('error', '获取表名失败', err);
239
- return [];
226
+ return filtered.map(item => item.name);
240
227
  }
228
+ // 使用原生方法提取表名
229
+ return list.map(item => item.name);
241
230
  };
242
231
 
243
232
  /**
@@ -247,38 +236,33 @@ DB.prototype.tables = async function (table, timeout = 15000) {
247
236
  * @returns {Promise|Array} 字段信息列表
248
237
  */
249
238
  DB.prototype.fields = async function (table, field_name, timeout = 15000) {
250
- try {
251
- const targetTable = table || this.table;
252
- if (!targetTable) {
253
- throw new TypeError('table must be specified');
254
- }
255
- var sql = 'PRAGMA table_info(`{0}`);'.replace('{0}', targetTable);
256
- var list = await this.run(sql, [], timeout);
257
- var len = list.length;
258
- for (var i = 0; i < len; i++) {
259
- list[i].pk = list[i].pk ? true : false;
260
- list[i].not_null = list[i].not_null ? true : false;
261
- }
262
-
263
- // 如果指定了字段名,过滤结果
264
- if (field_name) {
265
- list = list.filter(field => field.name === field_name);
266
- }
267
-
268
- return list.map(item => ({
269
- name: item.name,
270
- cid: item.cid,
271
- default_value: item.dflt_value,
272
- not_null: item.notnull,
273
- type: item.type,
274
- pk: item.pk,
275
- auto: item.auto,
276
- note: item.note
277
- }));
278
- } catch (err) {
279
- this.log('error', '获取字段信息失败', err);
280
- return [];
239
+ const targetTable = table || this.table;
240
+ if (!targetTable) {
241
+ throw new TypeError('table must be specified');
281
242
  }
243
+ var sql = 'PRAGMA table_info(`{0}`);'.replace('{0}', targetTable);
244
+ var list = await this.run(sql, [], timeout);
245
+ var len = list.length;
246
+ for (var i = 0; i < len; i++) {
247
+ list[i].pk = list[i].pk ? true : false;
248
+ list[i].not_null = list[i].not_null ? true : false;
249
+ }
250
+
251
+ // 如果指定了字段名,过滤结果
252
+ if (field_name) {
253
+ list = list.filter(field => field.name === field_name);
254
+ }
255
+
256
+ return list.map(item => ({
257
+ name: item.name,
258
+ cid: item.cid,
259
+ default_value: item.dflt_value,
260
+ not_null: item.notnull,
261
+ type: item.type,
262
+ pk: item.pk,
263
+ auto: item.auto,
264
+ note: item.note
265
+ }));
282
266
  };
283
267
 
284
268
  /**
@@ -424,42 +408,37 @@ DB.prototype.setType = function (field, type, value, not_null, auto) {
424
408
  * @returns {Promise | number} 创建成功返回1,失败返回0
425
409
  */
426
410
  DB.prototype.addTable = async function (table, field, type = 'int', auto = true, commit = '', timeout = 15000) {
427
- try {
428
- if (!table || typeof table !== 'string') {
429
- throw new TypeError('table must be non-empty string');
430
- }
431
- if (!field) {
432
- field = 'id';
433
- }
434
- // SQLite的自增主键要求字段类型必须是INTEGER(大写且不带长度)
435
- let fieldType;
436
- if (auto) {
437
- // 自增字段使用简单的INTEGER类型,由后面的PRIMARY KEY AUTOINCREMENT决定自增行为
438
- fieldType = 'INTEGER';
439
- } else {
440
- // 非自增字段使用正常的类型设置
441
- fieldType = this.setType(field, type, null, true, auto);
442
- }
443
- // 根据是否自增来构造不同的SQL语句
444
- let sqlTemplate;
445
- if (auto) {
446
- // 自增字段:使用INTEGER PRIMARY KEY AUTOINCREMENT语法
447
- sqlTemplate = 'CREATE TABLE IF NOT EXISTS `{0}` (`{1}` {2} PRIMARY KEY AUTOINCREMENT)';
448
- } else {
449
- // 非自增字段:使用正常的字段类型和主键定义
450
- sqlTemplate = 'CREATE TABLE IF NOT EXISTS `{0}` (`{1}` {2} PRIMARY KEY)';
451
- }
452
- var sql = sqlTemplate.replace('{0}', table).replace(
453
- '{1}', field).replace('{2}', fieldType) + ';';
454
- // SQLite不支持表级COMMENT语法,所以忽略commit参数
455
- var bl = await this.exec(sql, [], timeout);
456
- // 设置实例的表名属性,以便后续操作使用
457
- this.table = table;
458
- return bl;
459
- } catch (err) {
460
- this.log('error', '创建表失败', err);
461
- return 0;
462
- }
411
+ if (!table || typeof table !== 'string') {
412
+ throw new TypeError('table must be non-empty string');
413
+ }
414
+ if (!field) {
415
+ field = 'id';
416
+ }
417
+ // SQLite的自增主键要求字段类型必须是INTEGER(大写且不带长度)
418
+ let fieldType;
419
+ if (auto) {
420
+ // 自增字段使用简单的INTEGER类型,由后面的PRIMARY KEY AUTOINCREMENT决定自增行为
421
+ fieldType = 'INTEGER';
422
+ } else {
423
+ // 非自增字段使用正常的类型设置
424
+ fieldType = this.setType(field, type, null, true, auto);
425
+ }
426
+ // 根据是否自增来构造不同的SQL语句
427
+ let sqlTemplate;
428
+ if (auto) {
429
+ // 自增字段:使用INTEGER PRIMARY KEY AUTOINCREMENT语法
430
+ sqlTemplate = 'CREATE TABLE IF NOT EXISTS `{0}` (`{1}` {2} PRIMARY KEY AUTOINCREMENT)';
431
+ } else {
432
+ // 非自增字段:使用正常的字段类型和主键定义
433
+ sqlTemplate = 'CREATE TABLE IF NOT EXISTS `{0}` (`{1}` {2} PRIMARY KEY)';
434
+ }
435
+ var sql = sqlTemplate.replace('{0}', table).replace(
436
+ '{1}', field).replace('{2}', fieldType) + ';';
437
+ // SQLite不支持表级COMMENT语法,所以忽略commit参数
438
+ var bl = await this.exec(sql, [], timeout);
439
+ // 设置实例的表名属性,以便后续操作使用
440
+ this.table = table;
441
+ return bl;
463
442
  };
464
443
 
465
444
  /**
@@ -488,36 +467,32 @@ DB.prototype.emptyTable = function (table, timeout = 15000) {
488
467
  * @returns {Promise | number} 添加成功返回1,失败返回0
489
468
  */
490
469
  DB.prototype.addField = async function (field, type, value = '', not_null = true, auto = false, comment = '', timeout = 15000) {
491
- try {
492
- // 确保表名已设置
493
- if (!this.table || !field || !type) {
494
- throw new TypeError('table, field, and type must be specified');
495
- }
496
470
 
497
- // 在SQLite中,使用PRAGMA table_info检查表中是否已存在字段
498
- var sql = 'PRAGMA table_info(`{0}`)';
499
- sql = sql.replace('{0}', this.table);
500
- var columns = await this.run(sql, [], timeout);
501
- var fieldExists = false;
502
- for (var i = 0; i < columns.length; i++) {
503
- if (columns[i].name === field) {
504
- fieldExists = true;
505
- break;
506
- }
507
- }
471
+ // 确保表名已设置
472
+ if (!this.table || !field || !type) {
473
+ throw new TypeError('table, field, and type must be specified');
474
+ }
508
475
 
509
- if (!fieldExists) {
510
- var fieldType = this.setType(field, type, value, not_null, auto);
511
- var sql = 'ALTER Table `{0}` ADD `{1}` {2}';
512
- sql = sql.replace('{0}', this.table).replace('{1}', field).replace('{2}', fieldType) + ';';
513
- // SQLite不支持字段级COMMENT语法,所以忽略comment参数
514
- return await this.exec(sql, [], timeout);
476
+ // 在SQLite中,使用PRAGMA table_info检查表中是否已存在字段
477
+ var sql = 'PRAGMA table_info(`{0}`)';
478
+ sql = sql.replace('{0}', this.table);
479
+ var columns = await this.run(sql, [], timeout);
480
+ var fieldExists = false;
481
+ for (var i = 0; i < columns.length; i++) {
482
+ if (columns[i].name === field) {
483
+ fieldExists = true;
484
+ break;
515
485
  }
516
- return 0;
517
- } catch (err) {
518
- this.log('error', '添加字段失败', err);
519
- return 0;
520
486
  }
487
+
488
+ if (!fieldExists) {
489
+ var fieldType = this.setType(field, type, value, not_null, auto);
490
+ var sql = 'ALTER Table `{0}` ADD `{1}` {2}';
491
+ sql = sql.replace('{0}', this.table).replace('{1}', field).replace('{2}', fieldType) + ';';
492
+ // SQLite不支持字段级COMMENT语法,所以忽略comment参数
493
+ return await this.exec(sql, [], timeout);
494
+ }
495
+ return 0;
521
496
  };
522
497
 
523
498
  /**
@@ -533,53 +508,49 @@ DB.prototype.addField = async function (field, type, value = '', not_null = true
533
508
  * @returns {Promise | number} 修改成功返回1,失败返回0
534
509
  */
535
510
  DB.prototype.setField = async function (field, type, value = '', not_null = true, auto = false, isKey = false, new_name = '', timeout = 15000) {
536
- try {
537
- if (!field || !type || !this.table) {
538
- throw new TypeError('field, type, and table must be specified');
539
- }
540
511
 
541
- var sql =
542
- "select count(*) as `count` from sqlite_master where `type` = 'table' and `name` = '{1}' and `sql` like '%{2}%'";
543
- sql = sql.replace('{1}', this.table).replace('{2}', field);
544
- var arr = await this.run(sql, [], timeout);
545
- if (arr && arr.length > 0) {
546
- if (arr[0].count == 0) {
547
- return 0;
548
- }
549
- }
512
+ if (!field || !type || !this.table) {
513
+ throw new TypeError('field, type, and table must be specified');
514
+ }
550
515
 
551
- var field_type = this.setType(field, type, value, not_null, auto);
552
- if (field_type.has('text')) {
553
- field_type = field_type.replace('NOT NULL', '').replace("DEFAULT ''", '');
516
+ var sql =
517
+ "select count(*) as `count` from sqlite_master where `type` = 'table' and `name` = '{1}' and `sql` like '%{2}%'";
518
+ sql = sql.replace('{1}', this.table).replace('{2}', field);
519
+ var arr = await this.run(sql, [], timeout);
520
+ if (arr && arr.length > 0) {
521
+ if (arr[0].count == 0) {
522
+ return 0;
554
523
  }
524
+ }
555
525
 
556
- if (!new_name) {
557
- new_name = field;
558
- }
526
+ var field_type = this.setType(field, type, value, not_null, auto);
527
+ if (field_type.has('text')) {
528
+ field_type = field_type.replace('NOT NULL', '').replace("DEFAULT ''", '');
529
+ }
559
530
 
560
- sql = 'ALTER TABLE `{0}` ADD COLUMN `{2}` {3}';
561
- sql = sql.replace('{0}', this.table).replace('{2}', new_name).replace('{3}', field_type);
562
- if (isKey) {
563
- sql += ', DROP PRIMARY KEY, ADD PRIMARY KEY (' + new_name + ') USING BTREE;';
564
- } else {
565
- sql += ';';
566
- }
567
- await this.exec(sql, [], timeout);
531
+ if (!new_name) {
532
+ new_name = field;
533
+ }
568
534
 
569
- sql = 'UPDATE TABLE `{0}` SET `{2}` = `{1}`;';
570
- sql = sql.replace('{0}', this.table).replace('{1}', field).replace('{2}', new_name);
571
- var ret = await this.exec(sql, [], timeout);
535
+ sql = 'ALTER TABLE `{0}` ADD COLUMN `{2}` {3}';
536
+ sql = sql.replace('{0}', this.table).replace('{2}', new_name).replace('{3}', field_type);
537
+ if (isKey) {
538
+ sql += ', DROP PRIMARY KEY, ADD PRIMARY KEY (' + new_name + ') USING BTREE;';
539
+ } else {
540
+ sql += ';';
541
+ }
542
+ await this.exec(sql, [], timeout);
572
543
 
573
- if (field !== new_name) {
574
- // sql = "ALTER TABLE `{0}` DROP COLUMN `{1}`;";
575
- // sql = sql.replace('{0}', this.table).replace('{1}', field);
576
- // ret = await this.exec(sql);
577
- }
578
- return ret;
579
- } catch (err) {
580
- this.log('error', '修改字段失败', err);
581
- return 0;
544
+ sql = 'UPDATE TABLE `{0}` SET `{2}` = `{1}`;';
545
+ sql = sql.replace('{0}', this.table).replace('{1}', field).replace('{2}', new_name);
546
+ var ret = await this.exec(sql, [], timeout);
547
+
548
+ if (field !== new_name) {
549
+ // sql = "ALTER TABLE `{0}` DROP COLUMN `{1}`;";
550
+ // sql = sql.replace('{0}', this.table).replace('{1}', field);
551
+ // ret = await this.exec(sql);
582
552
  }
553
+ return ret;
583
554
  };
584
555
 
585
556
  /**
@@ -590,18 +561,13 @@ DB.prototype.setField = async function (field, type, value = '', not_null = true
590
561
  * @returns {Promise | number} 删除成功返回1,失败返回0
591
562
  */
592
563
  DB.prototype.delField = async function (table, field, timeout = 15000) {
593
- try {
594
- if (!table || !field) {
595
- throw new TypeError('table and field must be specified');
596
- }
597
-
598
- var sql = 'ALTER TABLE {0} DROP COLUMN {1};';
599
- sql = sql.replace('{0}', table).replace('{1}', field);
600
- return await this.exec(sql, [], timeout);
601
- } catch (err) {
602
- this.log('error', '删除字段失败', err);
603
- return 0;
564
+ if (!table || !field) {
565
+ throw new TypeError('table and field must be specified');
604
566
  }
567
+
568
+ var sql = 'ALTER TABLE {0} DROP COLUMN {1};';
569
+ sql = sql.replace('{0}', table).replace('{1}', field);
570
+ return await this.exec(sql, [], timeout);
605
571
  };
606
572
 
607
573
  /**
@@ -650,18 +616,13 @@ DB.prototype.sqlField = function (fd) {
650
616
  * @returns {Promise | number} 重命名成功返回1,失败返回0
651
617
  */
652
618
  DB.prototype.renameField = async function (table, field, new_field, type, timeout = 15000) {
653
- try {
654
- if (!table || !field || !new_field) {
655
- throw new TypeError('table, field, and new_field must be specified');
656
- }
657
-
658
- var sql = 'ALTER TABLE {0} RENAME COLUMN {1} TO {2};';
659
- sql = sql.replace('{0}', table).replace('{1}', field).replace('{2}', new_field);
660
- return await this.exec(sql, [], timeout);
661
- } catch (err) {
662
- this.log('error', '重命名字段失败', err);
663
- return 0;
619
+ if (!table || !field || !new_field) {
620
+ throw new TypeError('table, field, and new_field must be specified');
664
621
  }
622
+
623
+ var sql = 'ALTER TABLE {0} RENAME COLUMN {1} TO {2};';
624
+ sql = sql.replace('{0}', table).replace('{1}', field).replace('{2}', new_field);
625
+ return await this.exec(sql, [], timeout);
665
626
  };
666
627
 
667
628
  /**
@@ -731,16 +692,11 @@ DB.prototype.emptyTable = function (table, timeout = 15000) {
731
692
  * @returns {Promise | boolean} 存在返回true,不存在返回false
732
693
  */
733
694
  DB.prototype.hasTable = async function (table, timeout = 15000) {
734
- try {
735
- if (!table) {
736
- return false;
737
- }
738
- var list = await this.run("SELECT name FROM sqlite_master WHERE type='table' AND name=?;", [table], timeout);
739
- return list && list.length > 0;
740
- } catch (err) {
741
- this.log('error', '检查表是否存在失败', err);
695
+ if (!table) {
742
696
  return false;
743
697
  }
698
+ var list = await this.run("SELECT name FROM sqlite_master WHERE type='table' AND name=?;", [table], timeout);
699
+ return list && list.length > 0;
744
700
  };
745
701
 
746
702
  /**
@@ -751,16 +707,11 @@ DB.prototype.hasTable = async function (table, timeout = 15000) {
751
707
  * @returns {Promise | boolean} 存在返回true,不存在返回false
752
708
  */
753
709
  DB.prototype.hasField = async function (table, field, timeout = 15000) {
754
- try {
755
- if (!table || !field) {
756
- return false;
757
- }
758
- var fields = await this.fields(table, field, timeout);
759
- return fields && fields.some(f => f.name === field);
760
- } catch (err) {
761
- this.log('error', '检查字段是否存在失败', err);
710
+ if (!table || !field) {
762
711
  return false;
763
712
  }
713
+ var fields = await this.fields(table, field, timeout);
714
+ return fields && fields.some(f => f.name === field);
764
715
  };
765
716
 
766
717
  /**
@@ -788,16 +739,11 @@ DB.prototype.getCreateTable = async function (table, timeout = 15000) {
788
739
  if (!table) {
789
740
  throw new TypeError('table must be specified');
790
741
  }
791
- try {
792
- const list = await this.run("SELECT sql FROM sqlite_master WHERE type='table' AND name=?;", [table], timeout);
793
- if (list && list.length > 0) {
794
- return list[0].sql || '';
795
- }
796
- return '';
797
- } catch (err) {
798
- this.log('error', '获取表结构失败', err);
799
- return '';
742
+ const list = await this.run("SELECT sql FROM sqlite_master WHERE type='table' AND name=?;", [table], timeout);
743
+ if (list && list.length > 0) {
744
+ return list[0].sql || '';
800
745
  }
746
+ return '';
801
747
  };
802
748
 
803
749
  /**
@@ -811,51 +757,46 @@ DB.prototype.getTableData = async function (table, batch_size = 100, timeout = 6
811
757
  if (!table) {
812
758
  throw new TypeError('table must be specified');
813
759
  }
814
- try {
815
- // 获取表数据
816
- const rows = await this.run(`SELECT * FROM \`${table}\``, [], timeout);
817
- let sql = '';
818
-
819
- if (rows && rows.length > 0) {
820
- sql += `-- 表数据: ${table}\n`;
821
-
822
- // 批量处理大数据量
823
- for (let j = 0; j < rows.length; j += batch_size) {
824
- const batch = rows.slice(j, j + batch_size);
825
- for (const row of batch) {
826
- try {
827
- const row_data = Object.values(row)
828
- .map(value => {
829
- if (value === null) return 'NULL';
830
- if (typeof value === 'boolean') return value ? 1 : 0;
831
- if (typeof value === 'number') return value;
832
- if (value instanceof Date) {
833
- return "'" + value.toISOString().slice(0, 19).replace('T', ' ') + "'";
834
- }
835
- // 处理字符串,转义特殊字符
836
- if (typeof value === 'string') {
837
- return "'" + value
838
- .replace(/[\\']/g, '\\$&')
839
- .replace(/\n/g, '\\n')
840
- .replace(/\r/g, '\\r')
841
- .replace(/\t/g, '\\t')
842
- .replace(/\u0000/g, '\\0') + "'";
843
- }
844
- return "'" + String(value || '') + "'";
845
- }).join(',');
846
- sql += `INSERT INTO \`${table}\` VALUES (${row_data});\n`;
847
- } catch (rowErr) {
848
- this.log('error', '处理行数据失败', rowErr);
849
- }
760
+ // 获取表数据
761
+ const rows = await this.run(`SELECT * FROM \`${table}\``, [], timeout);
762
+ let sql = '';
763
+
764
+ if (rows && rows.length > 0) {
765
+ sql += `-- 表数据: ${table}\n`;
766
+
767
+ // 批量处理大数据量
768
+ for (let j = 0; j < rows.length; j += batch_size) {
769
+ const batch = rows.slice(j, j + batch_size);
770
+ for (const row of batch) {
771
+ try {
772
+ const row_data = Object.values(row)
773
+ .map(value => {
774
+ if (value === null) return 'NULL';
775
+ if (typeof value === 'boolean') return value ? 1 : 0;
776
+ if (typeof value === 'number') return value;
777
+ if (value instanceof Date) {
778
+ return "'" + value.toISOString().slice(0, 19).replace('T', ' ') + "'";
779
+ }
780
+ // 处理字符串,转义特殊字符
781
+ if (typeof value === 'string') {
782
+ return "'" + value
783
+ .replace(/[\\']/g, '\\$&')
784
+ .replace(/\n/g, '\\n')
785
+ .replace(/\r/g, '\\r')
786
+ .replace(/\t/g, '\\t')
787
+ .replace(/\u0000/g, '\\0') + "'";
788
+ }
789
+ return "'" + String(value || '') + "'";
790
+ }).join(',');
791
+ sql += `INSERT INTO \`${table}\` VALUES (${row_data});\n`;
792
+ } catch (rowErr) {
793
+ this.log('error', '处理行数据失败', rowErr);
850
794
  }
851
795
  }
852
- sql += '\n';
853
796
  }
854
- return sql;
855
- } catch (err) {
856
- this.log('error', '获取表数据失败', err);
857
- return '';
797
+ sql += '\n';
858
798
  }
799
+ return sql;
859
800
  };
860
801
 
861
802
  /**
@@ -866,15 +807,10 @@ DB.prototype.getTableData = async function (table, batch_size = 100, timeout = 6
866
807
  * @returns {Promise | number} 操作结果
867
808
  */
868
809
  DB.prototype.backup = function (table, backup, timeout = 60000) {
869
- try {
870
- if (!table || !backup) {
871
- throw new TypeError('table and backup must be specified');
872
- }
873
- return this.backupTable(table, backup, timeout);
874
- } catch (err) {
875
- this.log('error', '备份表失败', err);
876
- return 0;
810
+ if (!table || !backup) {
811
+ throw new TypeError('table and backup must be specified');
877
812
  }
813
+ return this.backupTable(table, backup, timeout);
878
814
  };
879
815
 
880
816
  /**