mm_sqlite 1.2.2 → 1.2.3

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
@@ -2,866 +2,918 @@ const { Sql } = require('./sql');
2
2
 
3
3
  /**
4
4
  * @class 数据库操作类
5
- * @extends Sql
5
+ * @augments Sql
6
6
  */
7
7
  class DB extends Sql {
8
- /**
9
- * @description 数据库管理器
10
- * @param {Object} mysql MySQL实例
11
- */
12
- constructor(mysql) {
13
- super(mysql.run, mysql.exec);
14
- // 保存mysql实例引用
15
- this._mysql = mysql;
16
- // 事务中
17
- this.task = 0;
18
-
19
- // 事务SQL
20
- this.task_sql = "";
21
- // 表名
22
- this.table = "";
23
-
24
- /**
25
- * 获取上级
26
- * @return {Object} 返回上级管理器
27
- */
28
- this.parent = function () {
29
- return mysql;
30
- };
31
- }
8
+ /**
9
+ * @description 数据库管理器
10
+ * @param {object} mysql MySQL实例
11
+ */
12
+ constructor(sqlite) {
13
+ super(sqlite.run, sqlite.exec);
14
+ // 保存mysql实例引用
15
+ this._sqlite = sqlite;
16
+ // 事务中
17
+ this.task = 0;
18
+
19
+ // 事务SQL
20
+ this.task_sql = '';
21
+ // 表名
22
+ this.table = '';
23
+
24
+ /**
25
+ * 获取上级
26
+ * @returns {object} 返回上级管理器
27
+ */
28
+ this.parent = function () {
29
+ return sqlite;
30
+ };
31
+ }
32
32
  }
33
33
 
34
34
  /**
35
35
  * 创建超时Promise
36
- * @param {Number} timeout - 超时时间(毫秒)
37
- * @param {String} message - 超时提示信息
38
- * @return {Promise} 超时Promise
36
+ * @param {number} timeout - 超时时间(毫秒)
37
+ * @param {string} message - 超时提示信息
38
+ * @returns {Promise} 超时Promise
39
39
  */
40
40
  DB.prototype._createTimeoutPromise = function (timeout, message) {
41
- return new Promise((_, reject) => {
42
- setTimeout(() => {
43
- reject(new Error(message));
44
- }, timeout);
45
- });
41
+ return new Promise((unused, reject) => {
42
+ setTimeout(() => {
43
+ reject(new Error(message));
44
+ }, timeout);
45
+ });
46
46
  };
47
47
 
48
48
  /**
49
49
  * 获取数据库名
50
- * @return {String} 数据库
50
+ * @returns {string} 数据库
51
51
  */
52
52
  DB.prototype.database = function () {
53
- return this.parent().config.database;
53
+ return this.parent().config.database;
54
54
  };
55
55
 
56
56
  /**
57
57
  * 构建新管理器
58
- * @param {String} table 表名
59
- * @param {String} key 键名
60
- * @return {Object} 返回管理器
58
+ * @param {string} table 表名
59
+ * @param {string} key 键名
60
+ * @returns {object} 返回管理器
61
61
  */
62
62
  DB.prototype.new = function (table, key) {
63
- var db = this.parent().db();
64
- db.table = table;
65
- if (key) {
66
- db.key = key;
67
- } else {
68
- var arr = table.split("_");
69
- db.key = arr[arr.length - 1] + "_id";
70
- }
71
- return db;
63
+ var db = this.parent().db();
64
+ db.table = table;
65
+ if (key) {
66
+ db.key = key;
67
+ } else {
68
+ var arr = table.split('_');
69
+ db.key = arr[arr.length - 1] + '_id';
70
+ }
71
+ return db;
72
72
  };
73
73
 
74
74
  /**
75
75
  * 获取数据库连接
76
- * @param {Number} timeout 超时时间(毫秒)
77
- * @returns {Promise<Object>} 数据库连接对象
76
+ * @param {number} timeout 超时时间(毫秒)
77
+ * @returns {Promise<object>} 数据库连接对象
78
78
  */
79
79
  DB.prototype.getConn = async function (timeout = 15000) {
80
- if (!this._mysql) {
81
- throw new Error('SQLite实例未初始化');
82
- }
83
- try {
84
- // 使用Promise.race实现超时控制
85
- return await Promise.race([
86
- this._mysql.getConn(),
87
- this._createTimeoutPromise(timeout, '获取数据库连接超时')
88
- ]);
89
- } catch (error) {
90
- this.logger('error', '获取连接失败', error);
91
- // 重新抛出异常,因为调用方需要连接对象
92
- throw error;
93
- }
80
+ if (!this._mysql) {
81
+ throw new Error('SQLite实例未初始化');
82
+ }
83
+ try {
84
+ // 使用Promise.race实现超时控制
85
+ return await Promise.race([
86
+ this._mysql.getConn(),
87
+ this._createTimeoutPromise(timeout, '获取数据库连接超时')
88
+ ]);
89
+ } catch (error) {
90
+ this.log('error', '获取连接失败', error);
91
+ // 重新抛出异常,因为调用方需要连接对象
92
+ throw error;
93
+ }
94
94
  };
95
95
 
96
96
  /**
97
- * 事务开始
98
- * @param {String} identifier 事务标识符
99
- * @param {Number} timeout 超时时间(毫秒)
100
- * @return {Promise<Object>} 执行结果
97
+ * 开始事务
98
+ * @returns {Promise<object>}
101
99
  */
102
- DB.prototype.start = async function (identifier = "point_1", timeout = 15000) {
103
- this.task = 1;
104
- try {
105
- return await this.exec("BEGIN;", [], timeout);
106
- } catch (err) {
107
- this.task = 0;
108
- this.logger('error', '事务开始失败', err);
109
- // 返回默认操作结果对象,保持返回值类型一致
110
- return 0;
111
- }
100
+ DB.prototype.start = async function() {
101
+ this.task = 1;
102
+ try {
103
+ await this.exec('BEGIN;', [], 15000);
104
+ // 返回事务对象
105
+ return {
106
+ commit: async () => {
107
+ await this.commit({});
108
+ },
109
+ rollback: async () => {
110
+ await this.back({});
111
+ }
112
+ };
113
+ } catch (err) {
114
+ this.task = 0;
115
+ this.log('error', '开始事务失败', err);
116
+ // 返回null作为默认值,保持返回值类型一致
117
+ return null;
118
+ }
112
119
  };
113
120
 
114
121
  /**
115
- * 提交
116
- * @param {Number} timeout 超时时间(毫秒)
117
- * @return {Promise<Object>} 执行结果
122
+ * 提交事务
123
+ * @param {object} transaction - 事务对象
124
+ * @returns {Promise<void>}
125
+ * @throws {TypeError} 当transaction参数无效时
118
126
  */
119
- DB.prototype.commit = async function (timeout = 15000) {
120
- if (this.task !== 1) {
121
- $.log.warn("[DB] [commit] 没有活跃的事务可提交");
122
- return 0;
123
- }
124
- this.task = 2;
125
- try {
126
- const result = await this.exec("COMMIT;", [], timeout);
127
- // 重置事务状态
128
- this.task = 0;
129
- this.task_sql = '';
130
- return result;
131
- } catch (err) {
132
- this.logger('error', '事务提交失败', err);
133
- // 尝试回滚
134
- try {
135
- await this.exec("ROLLBACK;", [], timeout);
136
- } catch (rollbackErr) {
137
- this.logger('error', '事务回滚也失败', rollbackErr);
138
- }
139
- this.task = 0;
140
- this.task_sql = '';
141
- }
127
+ DB.prototype.commit = async function(transaction) {
128
+ // 参数校验
129
+ if (!transaction || typeof transaction !== 'object') {
130
+ throw new TypeError('transaction must be object');
131
+ }
132
+
133
+ if (this.task !== 1) {
134
+ this.log('warn', '没有活跃的事务可提交');
135
+ return;
136
+ }
137
+
138
+ try {
139
+ await this.exec('COMMIT;', [], 15000);
140
+ this.task = 0;
141
+ } catch (err) {
142
+ this.log('error', '提交事务失败', err);
143
+ // 尝试回滚
144
+ try {
145
+ await this.exec('ROLLBACK;', [], 15000);
146
+ } catch (rollbackErr) {
147
+ this.log('error', '事务回滚也失败', rollbackErr);
148
+ }
149
+ this.task = 0;
150
+ this.task_sql = '';
151
+ }
142
152
  };
143
153
 
144
154
  /**
145
155
  * 事务结束
146
156
  */
147
157
  DB.prototype.end = function () {
148
- // 确保事务状态被重置
149
- this.task = 0;
150
- this.task_sql = '';
158
+ // 确保事务状态被重置
159
+ this.task = 0;
160
+ this.task_sql = '';
151
161
  };
152
162
 
153
163
  /**
154
- * 滚回
155
- * @param {String} identifier 事务标识符
156
- * @param {Number} timeout 超时时间(毫秒)
157
- * @return {Promise<Object>} 执行结果
164
+ * 回滚事务
165
+ * @param {object} transaction - 事务对象
166
+ * @returns {Promise<void>}
167
+ * @throws {TypeError} 当transaction参数无效时
158
168
  */
159
- DB.prototype.back = async function (identifier = "point_1", timeout = 15000) {
160
- if (this.task !== 1) {
161
- $.log.warn("[DB] [back] 没有活跃的事务可回滚");
162
- this.task = 0;
163
- this.task_sql = '';
164
- return 0;
165
- }
166
- this.task = 3;
167
- try {
168
- await this.exec("ROLLBACK;", [], timeout);
169
- const result = await this.exec("COMMIT;", [], timeout);
170
- // 重置事务状态
171
- this.task = 0;
172
- this.task_sql = '';
173
- return result;
174
- } catch (err) {
175
- this.logger('error', '事务回滚失败', err);
176
- this.task = 0;
177
- this.task_sql = '';
178
- return 0;
179
- }
169
+ DB.prototype.back = async function(transaction) {
170
+ // 参数校验
171
+ if (!transaction || typeof transaction !== 'object') {
172
+ throw new TypeError('transaction must be object');
173
+ }
174
+
175
+ if (this.task !== 1) {
176
+ this.log('warn', '没有活跃的事务可回滚');
177
+ return;
178
+ }
179
+
180
+ try {
181
+ await this.exec('ROLLBACK;', [], 15000);
182
+ this.task = 0;
183
+ this.task_sql = '';
184
+ } catch (err) {
185
+ this.log('error', '回滚事务失败', err);
186
+ this.task = 0;
187
+ this.task_sql = '';
188
+ }
189
+ };
190
+
191
+ /**
192
+ * 在事务中执行多个操作
193
+ * @param {Function} callback - 包含事务操作的回调函数
194
+ * @returns {Promise<*>}
195
+ * @throws {TypeError} 当callback参数无效时
196
+ */
197
+ DB.prototype.transaction = async function(callback) {
198
+ // 参数校验
199
+ if (typeof callback !== 'function') {
200
+ throw new TypeError('callback must be function');
201
+ }
202
+
203
+ try {
204
+ // 开始事务
205
+ await this.start();
206
+
207
+ // 执行回调函数
208
+ const result = await callback();
209
+
210
+ // 提交事务
211
+ await this.commit({});
212
+
213
+ return result;
214
+ } catch (err) {
215
+ // 回滚事务
216
+ await this.back({});
217
+ this.log('error', '事务执行失败', err);
218
+ // 返回null作为默认值,保持返回值类型一致
219
+ return null;
220
+ }
180
221
  };
181
222
 
182
223
  /**
183
224
  * @description 获取所有表名
184
- * @param {String} table 表名关键词, 可以 *table*包含、*table后缀、table*前缀 查询
185
- * @param {Number} timeout 超时时间(毫秒)
186
- * @return {Promise|Array} 表名数组
225
+ * @param {string} table 表名关键词, 可以 *table*包含、*table后缀、table*前缀 查询
226
+ * @param {number} timeout 超时时间(毫秒)
227
+ * @returns {Promise|Array} 表名数组
187
228
  */
188
229
  DB.prototype.tables = async function (table, timeout = 15000) {
189
- try {
190
- const list = await this.run("SELECT `name` FROM sqlite_master WHERE type='table';", [], timeout);
191
- if (table) {
192
- // 简单的过滤实现
193
- const filtered = [];
194
- for (const item of list) {
195
- const value = item.name;
196
- if (value && value.includes(table)) {
197
- filtered.push(item);
198
- }
199
- }
200
- return filtered.map(item => item.name);
201
- }
202
- // 使用原生方法提取表名
203
- return list.map(item => item.name);
204
- } catch (err) {
205
- this.logger('error', '获取表名失败', err);
206
- return [];
207
- }
230
+ try {
231
+ const list = await this.run("SELECT `name` FROM sqlite_master WHERE type='table';", [], timeout);
232
+ if (table) {
233
+ // 简单的过滤实现
234
+ const filtered = [];
235
+ for (const item of list) {
236
+ const value = item.name;
237
+ if (value && value.includes(table)) {
238
+ filtered.push(item);
239
+ }
240
+ }
241
+ return filtered.map(item => item.name);
242
+ }
243
+ // 使用原生方法提取表名
244
+ return list.map(item => item.name);
245
+ } catch (err) {
246
+ this.log('error', '获取表名失败', err);
247
+ return [];
248
+ }
208
249
  };
209
250
 
210
251
  /**
211
252
  * @description 获取所有表字段
212
- * @param {String} table 表名
213
- * @param {Number} timeout 超时时间(毫秒)
214
- * @return {Promise|Array} 字段信息列表
253
+ * @param {string} table 表名
254
+ * @param {number} timeout 超时时间(毫秒)
255
+ * @returns {Promise|Array} 字段信息列表
215
256
  */
216
- DB.prototype.fields = async function (table, timeout = 15000) {
217
- try {
218
- const targetTable = table || this.table;
219
- if (!table) {
220
- throw new TypeError('table must be specified');
221
- }
222
- var sql = "PRAGMA table_info(`{0}`);".replace('{0}', targetTable);
223
- var list = await this.run(sql, [], timeout);
224
- var len = list.length;
225
- for (var i = 0; i < len; i++) {
226
- list[i].pk = list[i].pk ? true : false;
227
- list[i].notnull = list[i].notnull ? true : false;
228
- }
229
- return list;
230
- } catch (err) {
231
- this.logger('error', '获取字段信息失败', err);
232
- return [];
233
- }
257
+ DB.prototype.fields = async function (table, field_name, timeout = 15000) {
258
+ try {
259
+ const targetTable = table || this.table;
260
+ if (!targetTable) {
261
+ throw new TypeError('table must be specified');
262
+ }
263
+ var sql = 'PRAGMA table_info(`{0}`);'.replace('{0}', targetTable);
264
+ var list = await this.run(sql, [], timeout);
265
+ var len = list.length;
266
+ for (var i = 0; i < len; i++) {
267
+ list[i].pk = list[i].pk ? true : false;
268
+ list[i].notnull = list[i].notnull ? true : false;
269
+ }
270
+
271
+ // 如果指定了字段名,过滤结果
272
+ if (field_name) {
273
+ list = list.filter(field => field.name === field_name);
274
+ }
275
+
276
+ return list;
277
+ } catch (err) {
278
+ this.log('error', '获取字段信息失败', err);
279
+ return [];
280
+ }
234
281
  };
235
282
 
236
283
  /**
237
284
  * @description 设置类型
238
- * @param {String} field 字段名
239
- * @param {String} type 类型名,常用类型 mediumint, int, varchar, datetime
240
- * @param {String} value 默认值
241
- * @param {Boolean} not_null 是否非空字段 true为非空,false为可空
242
- * @param {Boolean} auto 自动
243
- * @return {String} 返回最终类型
285
+ * @param {string} field 字段名
286
+ * @param {string} type 类型名,常用类型 mediumint, int, varchar, datetime
287
+ * @param {string} value 默认值
288
+ * @param {boolean} not_null 是否非空字段 true为非空,false为可空
289
+ * @param {boolean} auto 自动
290
+ * @returns {string} 返回最终类型
244
291
  */
245
292
  DB.prototype.setType = function (field, type, value, not_null, auto) {
246
- if (!type) {
247
- type = 'integer';
248
- }
249
- switch (type) {
250
- case "str":
251
- case "varchar":
252
- case "string":
253
- type = "varchar(255)";
254
- if (not_null) {
255
- type += " NOT NULL";
256
- }
257
- if (value) {
258
- type += " DEFAULT '" + value + "'";
259
- } else {
260
- type += " DEFAULT ''";
261
- }
262
- break;
263
- case "number":
264
- type = "integer(11) NOT NULL";
265
- if (auto) {
266
- type += " autoincrement";
267
- } else if (value) {
268
- type += " DEFAULT " + value;
269
- } else {
270
- type += " DEFAULT 0";
271
- }
272
- break;
273
- case "bool":
274
- case "tinyint":
275
- type = "tinyint(1) UNSIGNED NOT NULL";
276
- if (value) {
277
- type += " DEFAULT " + value;
278
- } else {
279
- type += " DEFAULT 0";
280
- }
281
- break;
282
- case "datetime":
283
- if (!value) {
284
- value = "1970-01-01 00:00:00";
285
- }
286
- type += " DEFAULT '" + value + "'";
287
- break;
288
- case "timestamp":
289
- if (auto) {
290
- if (field.indexOf('update') !== -1 || field.indexOf('last') !== -1) {
291
- type += " DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP";
292
- } else {
293
- type += " DEFAULT CURRENT_TIMESTAMP";
294
- }
295
- } else {
296
- type += " DEFAULT CURRENT_TIMESTAMP";
297
- }
298
- break;
299
- case "date":
300
- if (!value) {
301
- value = "1970-01-01";
302
- }
303
- type += " NOT NULL DEFAULT '" + value + "'";
304
- break;
305
- case "time":
306
- if (!value) {
307
- value = "00:00:00";
308
- }
309
- type += " NOT NULL DEFAULT '" + value + "'";
310
- break;
311
- case "double":
312
- if (type == "double") {
313
- type = "double(10, 2)"
314
- }
315
- type += " NOT NULL";
316
- if (value) {
317
- type += " DEFAULT '" + value + "'";
318
- } else {
319
- type += " DEFAULT 0";
320
- }
321
- break;
322
- case "float":
323
- if (type == "float") {
324
- type = "float(17, 8)"
325
- }
326
- type += " NOT NULL";
327
- if (value) {
328
- type += " DEFAULT '" + value + "'";
329
- } else {
330
- type += " DEFAULT 0";
331
- }
332
- break;
333
- case "longtext":
334
- case "text":
335
- if (type == "text") {
336
- type = "text NULL"
337
- } else if (type == "longtext") {
338
- type = "longtext NULL"
339
- }
340
- break;
341
- default:
342
- if (type.indexOf('var') !== -1) {
343
- if (not_null) {
344
- type += " NOT NULL"
345
- }
346
- if (value) {
347
- type += " DEFAULT '" + value + "'";
348
- } else {
349
- type += " DEFAULT ''";
350
- }
351
- } else {
352
- type += " UNSIGNED NOT NULL";
353
- if (auto) {
354
- type += " autoincrement";
355
- } else {
356
- if (value) {
357
- type += " DEFAULT '" + value + "'";
358
- } else {
359
- type += " DEFAULT 0";
360
- }
361
- }
362
- }
363
- break;
364
- }
365
- return type;
293
+ if (!type) {
294
+ type = 'integer';
295
+ }
296
+ switch (type) {
297
+ case 'str':
298
+ case 'varchar':
299
+ case 'string':
300
+ type = 'varchar(255)';
301
+ if (not_null) {
302
+ type += ' NOT NULL';
303
+ }
304
+ if (value) {
305
+ type += " DEFAULT '" + value + "'";
306
+ } else {
307
+ type += " DEFAULT ''";
308
+ }
309
+ break;
310
+ case 'number':
311
+ type = 'integer(11) NOT NULL';
312
+ if (auto) {
313
+ type += ' autoincrement';
314
+ } else if (value) {
315
+ type += ' DEFAULT ' + value;
316
+ } else {
317
+ type += ' DEFAULT 0';
318
+ }
319
+ break;
320
+ case 'bool':
321
+ case 'tinyint':
322
+ type = 'tinyint(1) UNSIGNED NOT NULL';
323
+ if (value) {
324
+ type += ' DEFAULT ' + value;
325
+ } else {
326
+ type += ' DEFAULT 0';
327
+ }
328
+ break;
329
+ case 'datetime':
330
+ if (!value) {
331
+ value = '1970-01-01 00:00:00';
332
+ }
333
+ type += " DEFAULT '" + value + "'";
334
+ break;
335
+ case 'timestamp':
336
+ if (auto) {
337
+ if (field.indexOf('update') !== -1 || field.indexOf('last') !== -1) {
338
+ type += ' DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP';
339
+ } else {
340
+ type += ' DEFAULT CURRENT_TIMESTAMP';
341
+ }
342
+ } else {
343
+ type += ' DEFAULT CURRENT_TIMESTAMP';
344
+ }
345
+ break;
346
+ case 'date':
347
+ if (!value) {
348
+ value = '1970-01-01';
349
+ }
350
+ type += " NOT NULL DEFAULT '" + value + "'";
351
+ break;
352
+ case 'time':
353
+ if (!value) {
354
+ value = '00:00:00';
355
+ }
356
+ type += " NOT NULL DEFAULT '" + value + "'";
357
+ break;
358
+ case 'double':
359
+ if (type == 'double') {
360
+ type = 'double(10, 2)';
361
+ }
362
+ type += ' NOT NULL';
363
+ if (value) {
364
+ type += " DEFAULT '" + value + "'";
365
+ } else {
366
+ type += ' DEFAULT 0';
367
+ }
368
+ break;
369
+ case 'float':
370
+ if (type == 'float') {
371
+ type = 'float(17, 8)';
372
+ }
373
+ type += ' NOT NULL';
374
+ if (value) {
375
+ type += " DEFAULT '" + value + "'";
376
+ } else {
377
+ type += ' DEFAULT 0';
378
+ }
379
+ break;
380
+ case 'longtext':
381
+ case 'text':
382
+ if (type == 'text') {
383
+ type = 'text NULL';
384
+ } else if (type == 'longtext') {
385
+ type = 'longtext NULL';
386
+ }
387
+ break;
388
+ default:
389
+ if (type.indexOf('var') !== -1) {
390
+ if (not_null) {
391
+ type += ' NOT NULL';
392
+ }
393
+ if (value) {
394
+ type += " DEFAULT '" + value + "'";
395
+ } else {
396
+ type += " DEFAULT ''";
397
+ }
398
+ } else {
399
+ type += ' UNSIGNED NOT NULL';
400
+ if (auto) {
401
+ type += ' autoincrement';
402
+ } else {
403
+ if (value) {
404
+ type += " DEFAULT '" + value + "'";
405
+ } else {
406
+ type += ' DEFAULT 0';
407
+ }
408
+ }
409
+ }
410
+ break;
411
+ }
412
+ return type;
366
413
  };
367
414
 
368
415
  /**
369
416
  * @description 创建数据表
370
- * @param {String} table 表名
371
- * @param {String} field 主键字段名
372
- * @param {String} type 类型名,常用类型 mediumint, int, varchar
373
- * @param {Boolean} auto 是否自增字段, 默认为自增字段
374
- * @param {String} commit 注释
375
- * @param {Number} timeout 超时时间(毫秒)
376
- * @return {Promise|Number} 创建成功返回1,失败返回0
417
+ * @param {string} table 表名
418
+ * @param {string} field 主键字段名
419
+ * @param {string} type 类型名,常用类型 mediumint, int, varchar
420
+ * @param {boolean} auto 是否自增字段, 默认为自增字段
421
+ * @param {string} commit 注释
422
+ * @param {number} timeout 超时时间(毫秒)
423
+ * @returns {Promise | number} 创建成功返回1,失败返回0
377
424
  */
378
425
  DB.prototype.addTable = async function (table, field, type = 'int', auto = true, commit = '', timeout = 15000) {
379
- try {
380
- if (!table || typeof table !== 'string') {
381
- throw new TypeError('table must be non-empty string');
382
- }
383
- if (!field) {
384
- field = "id";
385
- }
386
- // SQLite的自增主键要求字段类型必须是INTEGER(大写且不带长度)
387
- let fieldType;
388
- if (auto) {
389
- // 自增字段使用简单的INTEGER类型,由后面的PRIMARY KEY AUTOINCREMENT决定自增行为
390
- fieldType = "INTEGER";
391
- } else {
392
- // 非自增字段使用正常的类型设置
393
- fieldType = this.setType(field, type, null, true, auto);
394
- }
395
- // 根据是否自增来构造不同的SQL语句
396
- let sqlTemplate;
397
- if (auto) {
398
- // 自增字段:使用INTEGER PRIMARY KEY AUTOINCREMENT语法
399
- sqlTemplate = "CREATE TABLE IF NOT EXISTS `{0}` (`{1}` {2} PRIMARY KEY AUTOINCREMENT)";
400
- } else {
401
- // 非自增字段:使用正常的字段类型和主键定义
402
- sqlTemplate = "CREATE TABLE IF NOT EXISTS `{0}` (`{1}` {2} PRIMARY KEY)";
403
- }
404
- var sql = sqlTemplate.replace('{0}', table).replace(
405
- '{1}', field).replace('{2}', fieldType) + ";";
406
- // SQLite不支持表级COMMENT语法,所以忽略commit参数
407
- var bl = await this.exec(sql, [], timeout);
408
- // 设置实例的表名属性,以便后续操作使用
409
- this.table = table;
410
- return bl;
411
- } catch (err) {
412
- this.logger('error', '创建表失败', err);
413
- return 0;
414
- }
426
+ try {
427
+ if (!table || typeof table !== 'string') {
428
+ throw new TypeError('table must be non-empty string');
429
+ }
430
+ if (!field) {
431
+ field = 'id';
432
+ }
433
+ // SQLite的自增主键要求字段类型必须是INTEGER(大写且不带长度)
434
+ let fieldType;
435
+ if (auto) {
436
+ // 自增字段使用简单的INTEGER类型,由后面的PRIMARY KEY AUTOINCREMENT决定自增行为
437
+ fieldType = 'INTEGER';
438
+ } else {
439
+ // 非自增字段使用正常的类型设置
440
+ fieldType = this.setType(field, type, null, true, auto);
441
+ }
442
+ // 根据是否自增来构造不同的SQL语句
443
+ let sqlTemplate;
444
+ if (auto) {
445
+ // 自增字段:使用INTEGER PRIMARY KEY AUTOINCREMENT语法
446
+ sqlTemplate = 'CREATE TABLE IF NOT EXISTS `{0}` (`{1}` {2} PRIMARY KEY AUTOINCREMENT)';
447
+ } else {
448
+ // 非自增字段:使用正常的字段类型和主键定义
449
+ sqlTemplate = 'CREATE TABLE IF NOT EXISTS `{0}` (`{1}` {2} PRIMARY KEY)';
450
+ }
451
+ var sql = sqlTemplate.replace('{0}', table).replace(
452
+ '{1}', field).replace('{2}', fieldType) + ';';
453
+ // SQLite不支持表级COMMENT语法,所以忽略commit参数
454
+ var bl = await this.exec(sql, [], timeout);
455
+ // 设置实例的表名属性,以便后续操作使用
456
+ this.table = table;
457
+ return bl;
458
+ } catch (err) {
459
+ this.log('error', '创建表失败', err);
460
+ return 0;
461
+ }
415
462
  };
416
463
 
417
464
  /**
418
465
  * @description 清空数据表
419
- * @param {Boolean} reset 是否重置自增ID
420
- * @param {String} table 表名
421
- * @param {Number} timeout - 超时时间(毫秒)
422
- * @return {Promise|Number} 清空成功返回1,失败返回0
466
+ * @param {boolean} reset 是否重置自增ID
467
+ * @param {string} table 表名
468
+ * @param {number} timeout - 超时时间(毫秒)
469
+ * @returns {Promise | number} 清空成功返回1,失败返回0
423
470
  */
424
- DB.prototype.clearTable = async function (reset = true, table = '', timeout = 15000) {
425
- var sql = reset ? "TRUNCATE table `{0}`;" : "DELETE FROM `{0}`";
426
- var bl = await this.exec(sql.replace('{0}', table || this.table), [], timeout);
427
- return bl;
471
+ DB.prototype.emptyTable = function (table, timeout = 15000) {
472
+ if (!table || typeof table !== 'string') {
473
+ throw new TypeError('table must be a valid string');
474
+ }
475
+ return this.exec('DELETE FROM `' + table + '`;', timeout);
428
476
  };
429
477
 
430
478
  /**
431
479
  * @description 添加字段
432
- * @param {String} field 字段名
433
- * @param {String} type 类型名
434
- * @param {String} value 默认值
435
- * @param {Boolean} not_null 是否非空
436
- * @param {Boolean} auto 是否自增
437
- * @param {String} comment 注释
438
- * @param {Number} timeout 超时时间(毫秒)
439
- * @return {Promise|Number} 添加成功返回1,失败返回0
480
+ * @param {string} field 字段名
481
+ * @param {string} type 类型名
482
+ * @param {string} value 默认值
483
+ * @param {boolean} not_null 是否非空
484
+ * @param {boolean} auto 是否自增
485
+ * @param {string} comment 注释
486
+ * @param {number} timeout 超时时间(毫秒)
487
+ * @returns {Promise | number} 添加成功返回1,失败返回0
440
488
  */
441
489
  DB.prototype.addField = async function (field, type, value = '', not_null = true, auto = false, comment = '', timeout = 15000) {
442
- try {
443
- // 确保表名已设置
444
- if (!this.table || !field || !type) {
445
- throw new TypeError('table, field, and type must be specified');
446
- }
447
-
448
- // 在SQLite中,使用PRAGMA table_info检查表中是否已存在字段
449
- var sql = "PRAGMA table_info(`{0}`)";
450
- sql = sql.replace('{0}', this.table);
451
- var columns = await this.run(sql, [], timeout);
452
- var fieldExists = false;
453
- for (var i = 0; i < columns.length; i++) {
454
- if (columns[i].name === field) {
455
- fieldExists = true;
456
- break;
457
- }
458
- }
459
-
460
- if (!fieldExists) {
461
- var fieldType = this.setType(field, type, value, not_null, auto);
462
- var sql = "ALTER Table `{0}` ADD `{1}` {2}";
463
- sql = sql.replace('{0}', this.table).replace('{1}', field).replace('{2}', fieldType) + ";";
464
- // SQLite不支持字段级COMMENT语法,所以忽略comment参数
465
- return await this.exec(sql, [], timeout);
466
- }
467
- return 0;
468
- } catch (err) {
469
- this.logger('error', '添加字段失败', err);
470
- return 0;
471
- }
490
+ try {
491
+ // 确保表名已设置
492
+ if (!this.table || !field || !type) {
493
+ throw new TypeError('table, field, and type must be specified');
494
+ }
495
+
496
+ // 在SQLite中,使用PRAGMA table_info检查表中是否已存在字段
497
+ var sql = 'PRAGMA table_info(`{0}`)';
498
+ sql = sql.replace('{0}', this.table);
499
+ var columns = await this.run(sql, [], timeout);
500
+ var fieldExists = false;
501
+ for (var i = 0; i < columns.length; i++) {
502
+ if (columns[i].name === field) {
503
+ fieldExists = true;
504
+ break;
505
+ }
506
+ }
507
+
508
+ if (!fieldExists) {
509
+ var fieldType = this.setType(field, type, value, not_null, auto);
510
+ var sql = 'ALTER Table `{0}` ADD `{1}` {2}';
511
+ sql = sql.replace('{0}', this.table).replace('{1}', field).replace('{2}', fieldType) + ';';
512
+ // SQLite不支持字段级COMMENT语法,所以忽略comment参数
513
+ return await this.exec(sql, [], timeout);
514
+ }
515
+ return 0;
516
+ } catch (err) {
517
+ this.log('error', '添加字段失败', err);
518
+ return 0;
519
+ }
472
520
  };
473
521
 
474
522
  /**
475
523
  * @description 修改字段
476
- * @param {String} field 字段名
477
- * @param {String} type 类型名
478
- * @param {String} value 默认值
479
- * @param {Boolean} not_null 是否非空
480
- * @param {Boolean} auto 是否自增
481
- * @param {Boolean} isKey 是否主键
482
- * @param {String} new_name 新字段名
483
- * @param {Number} timeout 超时时间(毫秒)
484
- * @return {Promise|Number} 修改成功返回1,失败返回0
524
+ * @param {string} field 字段名
525
+ * @param {string} type 类型名
526
+ * @param {string} value 默认值
527
+ * @param {boolean} not_null 是否非空
528
+ * @param {boolean} auto 是否自增
529
+ * @param {boolean} isKey 是否主键
530
+ * @param {string} new_name 新字段名
531
+ * @param {number} timeout 超时时间(毫秒)
532
+ * @returns {Promise | number} 修改成功返回1,失败返回0
485
533
  */
486
534
  DB.prototype.setField = async function (field, type, value = '', not_null = true, auto = false, isKey = false, new_name = '', timeout = 15000) {
487
- try {
488
- if (!field || !type || !this.table) {
489
- throw new TypeError('field, type, and table must be specified');
490
- }
535
+ try {
536
+ if (!field || !type || !this.table) {
537
+ throw new TypeError('field, type, and table must be specified');
538
+ }
491
539
 
492
- var sql =
540
+ var sql =
493
541
  "select count(*) as `count` from sqlite_master where `type` = 'table' and `name` = '{1}' and `sql` like '%{2}%'";
494
- sql = sql.replace('{1}', this.table).replace('{2}', field);
495
- var arr = await this.run(sql, [], timeout);
496
- if (arr && arr.length > 0) {
497
- if (arr[0].count == 0) {
498
- return 0;
499
- }
500
- }
501
-
502
- var type = this.setType(field, type, value, not_null, auto);
503
- if (type.has('text')) {
504
- type = type.replace('NOT NULL', '').replace("DEFAULT ''", "");
505
- }
506
-
507
- if (!new_name) {
508
- new_name = field;
509
- }
510
-
511
- sql = "ALTER TABLE `{0}` ADD COLUMN `{2}` {3}";
512
- sql = sql.replace('{0}', this.table).replace('{2}', new_name).replace('{3}', type);
513
- if (isKey) {
514
- sql += ", DROP PRIMARY KEY, ADD PRIMARY KEY (" + new_name + ") USING BTREE;"
515
- } else {
516
- sql += ";";
517
- }
518
- await this.exec(sql, timeout);
519
-
520
- sql = "UPDATE TABLE `{0}` SET `{2}` = `{1}`;";
521
- sql = sql.replace('{0}', this.table).replace('{1}', field).replace('{2}', new_name);
522
- var ret = await this.exec(sql, timeout);
523
-
524
- if (field !== new_name) {
525
- // sql = "ALTER TABLE `{0}` DROP COLUMN `{1}`;";
526
- // sql = sql.replace('{0}', this.table).replace('{1}', field);
527
- // ret = await this.exec(sql);
528
- }
529
- return ret;
530
- } catch (err) {
531
- this.logger('error', '修改字段失败', err);
532
- return 0;
533
- }
542
+ sql = sql.replace('{1}', this.table).replace('{2}', field);
543
+ var arr = await this.run(sql, [], timeout);
544
+ if (arr && arr.length > 0) {
545
+ if (arr[0].count == 0) {
546
+ return 0;
547
+ }
548
+ }
549
+
550
+ var field_type = this.setType(field, type, value, not_null, auto);
551
+ if (field_type.has('text')) {
552
+ field_type = field_type.replace('NOT NULL', '').replace("DEFAULT ''", '');
553
+ }
554
+
555
+ if (!new_name) {
556
+ new_name = field;
557
+ }
558
+
559
+ sql = 'ALTER TABLE `{0}` ADD COLUMN `{2}` {3}';
560
+ sql = sql.replace('{0}', this.table).replace('{2}', new_name).replace('{3}', field_type);
561
+ if (isKey) {
562
+ sql += ', DROP PRIMARY KEY, ADD PRIMARY KEY (' + new_name + ') USING BTREE;';
563
+ } else {
564
+ sql += ';';
565
+ }
566
+ await this.exec(sql, timeout);
567
+
568
+ sql = 'UPDATE TABLE `{0}` SET `{2}` = `{1}`;';
569
+ sql = sql.replace('{0}', this.table).replace('{1}', field).replace('{2}', new_name);
570
+ var ret = await this.exec(sql, timeout);
571
+
572
+ if (field !== new_name) {
573
+ // sql = "ALTER TABLE `{0}` DROP COLUMN `{1}`;";
574
+ // sql = sql.replace('{0}', this.table).replace('{1}', field);
575
+ // ret = await this.exec(sql);
576
+ }
577
+ return ret;
578
+ } catch (err) {
579
+ this.log('error', '修改字段失败', err);
580
+ return 0;
581
+ }
534
582
  };
535
583
 
536
584
  /**
537
585
  * @description 删除字段
538
- * @param {String} table 表名
539
- * @param {String} field 字段名
540
- * @param {Number} timeout 超时时间(毫秒)
541
- * @return {Promise|Number} 删除成功返回1,失败返回0
586
+ * @param {string} table 表名
587
+ * @param {string} field 字段名
588
+ * @param {number} timeout 超时时间(毫秒)
589
+ * @returns {Promise | number} 删除成功返回1,失败返回0
542
590
  */
543
591
  DB.prototype.delField = async function (table, field, timeout = 15000) {
544
- try {
545
- if (!table || !field) {
546
- throw new TypeError('table and field must be specified');
547
- }
548
-
549
- var sql = "ALTER TABLE {0} DROP COLUMN {1};";
550
- sql = sql.replace('{0}', table).replace('{1}', field);
551
- return await this.exec(sql, [], timeout);
552
- } catch (err) {
553
- this.logger('error', '删除字段失败', err);
554
- return 0;
555
- }
592
+ try {
593
+ if (!table || !field) {
594
+ throw new TypeError('table and field must be specified');
595
+ }
596
+
597
+ var sql = 'ALTER TABLE {0} DROP COLUMN {1};';
598
+ sql = sql.replace('{0}', table).replace('{1}', field);
599
+ return await this.exec(sql, [], timeout);
600
+ } catch (err) {
601
+ this.log('error', '删除字段失败', err);
602
+ return 0;
603
+ }
556
604
  };
557
605
 
558
606
  /**
559
607
  * @description 拼接字段信息SQL
560
- * @param {Object} fd 字段信息
561
- * @return {String} sql语段
608
+ * @param {object} fd 字段信息
609
+ * @returns {string} sql语段
562
610
  */
563
611
  DB.prototype.sqlField = function (fd) {
564
- var sql = "`{0}`".replace('{0}', fd.name);
565
- sql += " " + fd.type;
566
- if (fd.notnull) {
567
- sql += " NOT NULL";
568
- }
569
- if (fd.auto) {
570
- if (fd.dflt_value) {
571
- if (fd.dflt_value === '0000-00-00 00:00:00') {
572
- fd.dflt_value = 'CURRENT_TIMESTAMP';
573
- }
574
- sql += " DEFAULT " + fd.dflt_value;
575
- }
576
- sql += " " + fd.auto;
577
- } else if (fd.dflt_value) {
578
- if (fd.dflt_value === '0000-00-00 00:00:00') {
579
- fd.dflt_value = '1970-01-01 00:00:00';
580
- }
581
- sql += " DEFAULT " + fd.dflt_value;
582
- }
583
- if (fd.note) {
584
- sql += " COMMENT '" + fd.note + "'";
585
- }
586
- if (fd.pk) {
587
- sql += " PRIMARY KEY";
588
- }
589
- return sql;
612
+ var sql = '`{0}`'.replace('{0}', fd.name);
613
+ sql += ' ' + fd.type;
614
+ if (fd.notnull) {
615
+ sql += ' NOT NULL';
616
+ }
617
+ if (fd.auto) {
618
+ if (fd.dflt_value) {
619
+ if (fd.dflt_value === '0000-00-00 00:00:00') {
620
+ fd.dflt_value = 'CURRENT_TIMESTAMP';
621
+ }
622
+ sql += ' DEFAULT ' + fd.dflt_value;
623
+ }
624
+ sql += ' ' + fd.auto;
625
+ } else if (fd.dflt_value) {
626
+ if (fd.dflt_value === '0000-00-00 00:00:00') {
627
+ fd.dflt_value = '1970-01-01 00:00:00';
628
+ }
629
+ sql += ' DEFAULT ' + fd.dflt_value;
630
+ }
631
+ if (fd.note) {
632
+ sql += " COMMENT '" + fd.note + "'";
633
+ }
634
+ if (fd.pk) {
635
+ sql += ' PRIMARY KEY';
636
+ }
637
+ return sql;
590
638
  };
591
639
 
592
640
  /**
593
641
  * @description 重命名字段
594
- * @param {String} table 表名
595
- * @param {String} field 字段名
596
- * @param {String} new_field 新字段名
597
- * @param {String} type 字段类型
598
- * @param {Number} timeout 超时时间(毫秒)
599
- * @return {Promise|Number} 重命名成功返回1,失败返回0
642
+ * @param {string} table 表名
643
+ * @param {string} field 字段名
644
+ * @param {string} new_field 新字段名
645
+ * @param {string} type 字段类型
646
+ * @param new_name
647
+ * @param unused_type
648
+ * @param {number} timeout 超时时间(毫秒)
649
+ * @returns {Promise | number} 重命名成功返回1,失败返回0
600
650
  */
601
651
  DB.prototype.renameField = async function (table, field, new_field, type, timeout = 15000) {
602
- try {
603
- if (!table || !field || !new_field) {
604
- throw new TypeError('table, field, and new_field must be specified');
605
- }
606
-
607
- var sql = "ALTER TABLE {0} RENAME COLUMN {1} TO {2};";
608
- sql = sql.replace('{0}', table).replace('{1}', field).replace('{2}', new_field);
609
- return await this.exec(sql, [], timeout);
610
- } catch (err) {
611
- this.logger('error', '重命名字段失败', err);
612
- return 0;
613
- }
652
+ try {
653
+ if (!table || !field || !new_field) {
654
+ throw new TypeError('table, field, and new_field must be specified');
655
+ }
656
+
657
+ var sql = 'ALTER TABLE {0} RENAME COLUMN {1} TO {2};';
658
+ sql = sql.replace('{0}', table).replace('{1}', field).replace('{2}', new_field);
659
+ return await this.exec(sql, [], timeout);
660
+ } catch (err) {
661
+ this.log('error', '重命名字段失败', err);
662
+ return 0;
663
+ }
614
664
  };
615
665
 
616
666
  /**
617
667
  * @description 修改字段类型
618
- * @param {String} table 表名
619
- * @param {String} field 字段名
620
- * @param {String} type 字段类型
621
- * @param {Number} timeout 超时时间(毫秒)
622
- * @return {Promise|Number} 操作结果
668
+ * @param {string} table 表名
669
+ * @param {string} field 字段名
670
+ * @param {string} type 字段类型
671
+ * @param {number} timeout 超时时间(毫秒)
672
+ * @returns {Promise | number} 操作结果
623
673
  */
624
674
  DB.prototype.editField = function (table, field, type, timeout = 15000) {
625
- try {
626
- if (!table || !field || !type) {
627
- throw new TypeError('table, field, and type must be specified');
628
- }
629
- return this.exec("ALTER TABLE `" + table + "` MODIFY COLUMN `" + field + "` " + type + ";", [], timeout);
630
- } catch (err) {
631
- this.logger('error', '修改字段类型失败', err);
632
- return 0;
633
- }
675
+ try {
676
+ if (!table || !field || !type) {
677
+ throw new TypeError('table, field, and type must be specified');
678
+ }
679
+ return this.exec('ALTER TABLE `' + table + '` MODIFY COLUMN `' + field + '` ' + type + ';', [], timeout);
680
+ } catch (err) {
681
+ this.log('error', '修改字段类型失败', err);
682
+ return 0;
683
+ }
634
684
  };
635
685
 
636
686
  /**
637
687
  * @description 删除数据表
638
- * @param {String} table 表名
639
- * @param {Number} timeout - 超时时间(毫秒)
640
- * @return {Promise|Number} 删除成功返回1,失败返回0
688
+ * @param {string} table 表名
689
+ * @param {number} timeout - 超时时间(毫秒)
690
+ * @returns {Promise | number} 删除成功返回1,失败返回0
641
691
  */
642
692
  DB.prototype.dropTable = function (table, timeout = 15000) {
643
- if (!table) {
644
- throw new TypeError('table must be specified');
645
- }
646
- return this.exec("DROP TABLE IF EXISTS `" + table + "`;", [], timeout);
693
+ if (!table) {
694
+ throw new TypeError('table must be specified');
695
+ }
696
+ return this.exec('DROP TABLE IF EXISTS `' + table + '`;', [], timeout);
647
697
  };
648
698
 
649
699
  /**
650
700
  * @description 重命名数据表
651
- * @param {String} table 原表名
652
- * @param {String} new_table 新表名
653
- * @param {Number} timeout - 超时时间(毫秒)
654
- * @return {Promise|Number} 重命名成功返回1,失败返回0
701
+ * @param {string} table 原表名
702
+ * @param {string} new_table 新表名
703
+ * @param {number} timeout - 超时时间(毫秒)
704
+ * @returns {Promise | number} 重命名成功返回1,失败返回0
655
705
  */
656
706
  DB.prototype.renameTable = function (table, new_table, timeout = 15000) {
657
- if (!table || !new_table) {
658
- throw new TypeError('table and new_table must be specified');
659
- }
660
- return this.exec("ALTER TABLE `" + table + "` RENAME TO `" + new_table + "`;", [], timeout);
707
+ if (!table || !new_table) {
708
+ throw new TypeError('table and new_table must be specified');
709
+ }
710
+ return this.exec('ALTER TABLE `' + table + '` RENAME TO `' + new_table + '`;', [], timeout);
661
711
  };
662
712
 
663
713
  /**
664
714
  * @description 清空数据表(保留表结构)
665
- * @param {String} table 表名
666
- * @param {Number} timeout - 超时时间(毫秒)
667
- * @return {Promise|Number} 清空成功返回1,失败返回0
715
+ * @param {string} table 表名
716
+ * @param {number} timeout - 超时时间(毫秒)
717
+ * @returns {Promise | number} 清空成功返回1,失败返回0
668
718
  */
669
719
  DB.prototype.emptyTable = function (table, timeout = 15000) {
670
- if (!table) {
671
- throw new TypeError('table must be specified');
672
- }
673
- return this.exec("DELETE FROM `" + table + "`;", [], timeout);
720
+ if (!table) {
721
+ throw new TypeError('table must be specified');
722
+ }
723
+ return this.exec('DELETE FROM `' + table + '`;', [], timeout);
674
724
  };
675
725
 
676
726
  /**
677
727
  * @description 检查表是否存在
678
- * @param {String} table 表名
679
- * @param {Number} timeout - 超时时间(毫秒)
680
- * @return {Promise|Boolean} 存在返回true,不存在返回false
728
+ * @param {string} table 表名
729
+ * @param {number} timeout - 超时时间(毫秒)
730
+ * @returns {Promise | boolean} 存在返回true,不存在返回false
681
731
  */
682
732
  DB.prototype.hasTable = async function (table, timeout = 15000) {
683
- try {
684
- if (!table) {
685
- return false;
686
- }
687
- var list = await this.run("SELECT name FROM sqlite_master WHERE type='table' AND name=?;", [table], timeout);
688
- return list && list.length > 0;
689
- } catch (err) {
690
- this.logger('error', '检查表是否存在失败', err);
691
- return false;
692
- }
733
+ try {
734
+ if (!table) {
735
+ return false;
736
+ }
737
+ var list = await this.run("SELECT name FROM sqlite_master WHERE type='table' AND name=?;", [table], timeout);
738
+ return list && list.length > 0;
739
+ } catch (err) {
740
+ this.log('error', '检查表是否存在失败', err);
741
+ return false;
742
+ }
693
743
  };
694
744
 
695
745
  /**
696
746
  * @description 检查字段是否存在
697
- * @param {String} table 表名
698
- * @param {String} field 字段名
699
- * @param {Number} timeout - 超时时间(毫秒)
700
- * @return {Promise|Boolean} 存在返回true,不存在返回false
747
+ * @param {string} table 表名
748
+ * @param {string} field 字段名
749
+ * @param {number} timeout - 超时时间(毫秒)
750
+ * @returns {Promise | boolean} 存在返回true,不存在返回false
701
751
  */
702
752
  DB.prototype.hasField = async function (table, field, timeout = 15000) {
703
- try {
704
- if (!table || !field) {
705
- return false;
706
- }
707
- var fields = await this.fields(table, field, timeout);
708
- return fields && fields.some(f => f.name === field);
709
- } catch (err) {
710
- this.logger('error', '检查字段是否存在失败', err);
711
- return false;
712
- }
753
+ try {
754
+ if (!table || !field) {
755
+ return false;
756
+ }
757
+ var fields = await this.fields(table, field, timeout);
758
+ return fields && fields.some(f => f.name === field);
759
+ } catch (err) {
760
+ this.log('error', '检查字段是否存在失败', err);
761
+ return false;
762
+ }
713
763
  };
714
764
 
715
765
  /**
716
766
  * @description 备份数据表
717
- * @param {String} table 原表名
718
- * @param {String} backup 备份表名
719
- * @param {Number} timeout - 超时时间(毫秒)
720
- * @return {Promise|Number} 备份成功返回1,失败返回0
767
+ * @param {string} table 原表名
768
+ * @param {string} backup 备份表名
769
+ * @param {number} timeout - 超时时间(毫秒)
770
+ * @returns {Promise | number} 备份成功返回1,失败返回0
721
771
  */
722
772
  DB.prototype.backupTable = function (table, backup, timeout = 60000) {
723
- if (!table || !backup) {
724
- throw new TypeError('table and backup must be specified');
725
- }
726
- var sql = "CREATE TABLE IF NOT EXISTS `" + backup + "` AS SELECT * FROM `" + table + "`;";
727
- return this.exec(sql, [], timeout);
773
+ if (!table || !backup) {
774
+ throw new TypeError('table and backup must be specified');
775
+ }
776
+ var sql = 'CREATE TABLE IF NOT EXISTS `' + backup + '` AS SELECT * FROM `' + table + '`;';
777
+ return this.exec(sql, [], timeout);
728
778
  };
729
779
 
730
780
  /**
731
781
  * @description 获取表创建语句
732
- * @param {String} table 表名
733
- * @param {Number} timeout 超时时间(毫秒)
734
- * @return {Promise|String} 创建语句
782
+ * @param {string} table 表名
783
+ * @param {number} timeout 超时时间(毫秒)
784
+ * @returns {Promise | string} 创建语句
735
785
  */
736
786
  DB.prototype.getCreateTable = async function (table, timeout = 15000) {
737
- try {
738
- if (!table) {
739
- throw new TypeError('table must be specified');
740
- }
741
- const list = await this.run("SELECT sql FROM sqlite_master WHERE type='table' AND name=?;", [table], timeout);
742
- if (list && list.length > 0) {
743
- return list[0].sql || '';
744
- }
745
- return '';
746
- } catch (err) {
747
- this.logger('error', '获取表结构失败', err);
748
- return '';
749
- }
787
+ if (!table) {
788
+ throw new TypeError('table must be specified');
789
+ }
790
+ try {
791
+ const list = await this.run("SELECT sql FROM sqlite_master WHERE type='table' AND name=?;", [table], timeout);
792
+ if (list && list.length > 0) {
793
+ return list[0].sql || '';
794
+ }
795
+ return '';
796
+ } catch (err) {
797
+ this.log('error', '获取表结构失败', err);
798
+ return '';
799
+ }
750
800
  };
751
801
 
752
802
  /**
753
803
  * @description 获取表数据的SQL插入语句
754
- * @param {String} table 表名
755
- * @param {Number} batchSize 批量处理大小
756
- * @param {Number} timeout 超时时间(毫秒)
757
- * @return {Promise|String} SQL插入语句
804
+ * @param {string} table 表名
805
+ * @param {number} batchSize 批量处理大小
806
+ * @param batch_size
807
+ * @param {number} timeout 超时时间(毫秒)
808
+ * @returns {Promise | string} SQL插入语句
758
809
  */
759
810
  DB.prototype.getTableData = async function (table, batchSize = 100, timeout = 60000) {
760
- try {
761
- if (!table) {
762
- throw new TypeError('table must be specified');
763
- }
764
- // 获取表数据
765
- const rows = await this.run(`SELECT * FROM \`${table}\``, [], timeout);
766
- let sql = '';
767
-
768
- if (rows && rows.length > 0) {
769
- sql += `-- 表数据: ${table}\n`;
770
-
771
- // 批量处理大数据量
772
- for (let j = 0; j < rows.length; j += batchSize) {
773
- const batch = rows.slice(j, j + batchSize);
774
- for (const row of batch) {
775
- try {
776
- const rowValues = Object.values(row)
777
- .map(value => {
778
- if (value === null) return 'NULL';
779
- if (typeof value === 'boolean') return value ? 1 : 0;
780
- if (typeof value === 'number') return value;
781
- if (value instanceof Date) {
782
- return "'" + value.toISOString().slice(0, 19).replace('T', ' ') + "'";
783
- }
784
- // 处理字符串,转义特殊字符
785
- if (typeof value === 'string') {
786
- return "'" + value
787
- .replace(/[\\']/g, '\\$&')
788
- .replace(/\n/g, '\\n')
789
- .replace(/\r/g, '\\r')
790
- .replace(/\t/g, '\\t')
791
- .replace(/\u0000/g, '\\0') + "'";
792
- }
793
- return "'" + String(value || '') + "'";
794
- }).join(',');
795
- sql += `INSERT INTO \`${table}\` VALUES (${rowValues});\n`;
796
- } catch (rowErr) {
797
- this.logger('error', '处理行数据失败', rowErr);
798
- }
799
- }
800
- }
801
- sql += '\n';
802
- }
803
- return sql;
804
- } catch (err) {
805
- this.logger('error', '获取表数据失败', err);
806
- return '';
807
- }
811
+ if (!table) {
812
+ throw new TypeError('table must be specified');
813
+ }
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
+ }
850
+ }
851
+ }
852
+ sql += '\n';
853
+ }
854
+ return sql;
855
+ } catch (err) {
856
+ this.log('error', '获取表数据失败', err);
857
+ return '';
858
+ }
808
859
  };
809
860
 
810
861
  /**
811
862
  * @description 备份表
812
- * @param {String} table 表名
813
- * @param {String} backup 备份表名
814
- * @param {Number} timeout 超时时间(毫秒)
815
- * @return {Promise|Number} 操作结果
863
+ * @param {string} table 表名
864
+ * @param {string} backup 备份表名
865
+ * @param {number} timeout 超时时间(毫秒)
866
+ * @returns {Promise | number} 操作结果
816
867
  */
817
868
  DB.prototype.backup = function (table, backup, timeout = 60000) {
818
- try {
819
- if (!table || !backup) {
820
- throw new TypeError('table and backup must be specified');
821
- }
822
- return this.backupTable(table, backup, timeout);
823
- } catch (err) {
824
- this.logger('error', '备份表失败', err);
825
- return 0;
826
- }
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;
877
+ }
827
878
  };
828
879
 
829
880
  /**
830
881
  * @description 创建表
831
- * @param {String} table 表名
832
- * @param {Object} model 表模型,键值对,根据值类型创建字段类型,根据键名创建字段名
833
- * @param {String} key 主键
834
- * @return {Promise|Number} 操作结果
882
+ * @param {string} table 表名
883
+ * @param {object} model 表模型,键值对,根据值类型创建字段类型,根据键名创建字段名
884
+ * @param {string} key 主键
885
+ * @param timeout
886
+ * @returns {Promise | number} 操作结果
835
887
  */
836
888
  DB.prototype.createTable = function (table, model, key = 'id', timeout = 15000) {
837
- if (!table || !model) {
838
- throw new TypeError('table, model must be specified');
839
- }
840
- var fields = '';
841
- for (const field in model) {
842
- const value = model[field];
843
- let type = '';
844
- if (field === key) {
845
- type = 'INTEGER PRIMARY KEY AUTOINCREMENT';
846
- } else if (typeof value === 'number') {
847
- if (value % 1 === 0) {
848
- type = 'INTEGER';
849
- } else {
850
- type = 'REAL';
851
- }
852
- } else if (typeof value === 'string') {
853
- type = 'TEXT';
854
- }
855
- else {
856
- type = 'BLOB';
857
- }
858
- fields += `\`${field}\` ${type}, `;
859
- }
860
- fields = fields.slice(0, -2);
861
- var sql = `CREATE TABLE IF NOT EXISTS \`${table}\` (${fields});`;
862
- return this.exec(sql, [], timeout);
863
- }
889
+ if (!table || !model) {
890
+ throw new TypeError('table, model must be specified');
891
+ }
892
+ var fields = '';
893
+ for (const field in model) {
894
+ const value = model[field];
895
+ let type = '';
896
+ if (field === key) {
897
+ type = 'INTEGER PRIMARY KEY AUTOINCREMENT';
898
+ } else if (typeof value === 'number') {
899
+ if (value % 1 === 0) {
900
+ type = 'INTEGER';
901
+ } else {
902
+ type = 'REAL';
903
+ }
904
+ } else if (typeof value === 'string') {
905
+ type = 'TEXT';
906
+ }
907
+ else {
908
+ type = 'BLOB';
909
+ }
910
+ fields += `\`${field}\` ${type}, `;
911
+ }
912
+ fields = fields.slice(0, -2);
913
+ var sql = `CREATE TABLE IF NOT EXISTS \`${table}\` (${fields});`;
914
+ return this.exec(sql, [], timeout);
915
+ };
864
916
 
865
917
  module.exports = {
866
- DB
918
+ DB
867
919
  };