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