mm_sqlite 1.0.6 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -1,224 +1,724 @@
1
- const resolve = require('path').resolve;
2
1
  const sqlite3 = require('sqlite3').verbose();
3
- const {
4
- DB
5
- } = require('./db');
6
-
7
- const Link_model = require('./link_model');
8
-
9
- var pool = {};
10
-
11
- /// 数据库封装
12
- class Sqlite {
13
- /**
14
- * @description 创建Redis帮助类函数 (构造函数)
15
- * @param {String} scope 作用域
16
- * @param {String} dir 当前路径
17
- * @constructor
18
- */
19
- constructor(scope, dir) {
20
- // 作用域
21
- this.scope;
22
- if (scope) {
23
- this.scope = scope;
24
- } else {
25
- this.scope = $.val.scope + '';
26
- }
27
- // 当前目录
28
- this.dir = __dirname;
29
- if (dir) {
30
- this.dir = dir;
31
- }
32
- // 错误提示
33
- this.error;
34
- /**
35
- * sql语句
36
- */
37
- this.sql = "";
38
- // 执行结果
39
- this.results = [];
40
- // 连接器
41
- this.conn;
42
-
43
- // 数据库配置参数
44
- this.config = {
45
- // 服务器地址
46
- host: "./db/".fullname(this.dir),
47
- // 数据库
48
- database: "mm"
49
- };
50
-
51
- // 唯一标识符
52
- this.identifier = resolve(this.config.host, this.config.database);
53
-
54
- // 定义当前类, 用于数据库实例化访问
55
- var $this = this;
56
-
57
- /**
58
- * @description 查询sql
59
- * @param {String} sql 查询参
60
- * @param {Array} val 替换值
61
- * @return {Promise|Array} 异步构造器, 当await时返回执行结果
62
- */
63
- this.run = function(sql, val) {
64
- sql = sql.replaceAll("&&", "AND").replaceAll("||", "OR").replaceAll("varchar", "text").replaceAll(" int", " integer");
65
- var _this = this;
66
- this.sql = sql;
67
-
68
- // 返回一个 Promise
69
- return new Promise((resolve, reject) => {
70
- $this.conn.all(sql, val, function(err, rows) {
71
- if (err) {
72
- // reject(err);
73
- _this.error = {
74
- code: err.errno,
75
- message: $.info(err).between('Error: ', ']')
76
- };
77
- resolve(rows || []);
78
- } else {
79
- _this.error = undefined;
80
- resolve(rows || []);
81
- }
82
- });
83
- });
84
- };
85
-
86
- /**
87
- * @description 增删改sql
88
- * @param {String} sql 查询参
89
- * @param {Array} val 替换值
90
- * @return {Promise|Array} 异步构造器, 当await时返回执行结果
91
- */
92
- this.exec = function(sql) {
93
- sql = sql.replaceAll("&&", "AND").replaceAll("||", "OR").replaceAll("varchar", "text").replaceAll(" int", " integer");
94
- var _this = this;
95
- this.sql = sql;
96
- // 返回一个 Promise
97
- return new Promise((resolve, reject) => {
98
- $this.conn.run(sql, function(err, rows) {
99
- if (err) {
100
- // reject(err);
101
- _this.error = {
102
- code: err.errno,
103
- message: $.info(err).between('Error: ', ']')
104
- };
105
- resolve(0);
106
- } else {
107
- _this.error = undefined;
108
- resolve(1);
109
- }
110
- });
111
- });
112
- };
113
-
114
- /**
115
- * @description 获取数据库管理器
116
- */
117
- this.db = function() {
118
- return new DB($this);
119
- };
120
- }
2
+ const DB = require('./db');
3
+ const { BaseService } = require('mm_base_service');
4
+
5
+ /**
6
+ * SQLite数据库操作类
7
+ * @class Sqlite
8
+ * @extends BaseService
9
+ */
10
+ class Sqlite extends BaseService {
11
+ /**
12
+ * 默认配置
13
+ */
14
+ static default_config = {
15
+ host: "/db/".fullname(),
16
+ port: 3306,
17
+ user: "root",
18
+ password: "",
19
+ database: "mm",
20
+ charset: "utf8mb4",
21
+ timezone: "+08:00",
22
+ connect_timeout: 20000,
23
+ acquire_timeout: 20000,
24
+ query_timeout: 20000,
25
+ connection_limit: 1,
26
+ queue_limit: 0,
27
+ enable_keep_alive: true,
28
+ keep_alive_initial_delay: 10000,
29
+ enable_reconnect: true,
30
+ reconnect_interval: 1000,
31
+ max_reconnect_attempts: 5,
32
+ wait_for_connections: true
33
+ };
34
+
35
+ /**
36
+ * 构造函数
37
+ * @param {Object} config - 配置对象
38
+ */
39
+ constructor(config) {
40
+ const merged_config = Object.assign({}, Sqlite.default_config, config || {});
41
+ super(merged_config);
42
+
43
+ this.config = merged_config;
44
+ this._connection = null;
45
+ this._pool = null;
46
+ this._status = 'closed';
47
+ this._last_connect_time = 0;
48
+ this._reconnecting = false;
49
+ this._is_inited = false;
50
+ this._is_destroyed = false;
51
+ this._db = null;
52
+ this._open = false;
53
+ this._conn_retry_count = 0;
54
+ }
121
55
  }
122
56
 
123
57
  /**
124
- * 设置配置参数
125
- * @param {Object} cg 配置对象或配置路径
58
+ * 初始化服务
59
+ * @returns {Promise<void>}
126
60
  */
127
- Sqlite.prototype.setConfig = function(cg) {
128
- var obj;
129
- if (typeof(cg) === "string") {
130
- obj = cg.loadJson(this.dir);
131
- } else {
132
- obj = cg;
133
- }
134
- $.push(this.config, obj);
135
- this.identifier = resolve(this.config.host, this.config.database);
136
- };
137
-
138
- /**
139
- * @description 打开数据库, 如果没有则建立数据库连接再打开
140
- */
141
- Sqlite.prototype.open = function() {
142
- if (!pool[this.identifier]) {
143
- var file = resolve(this.config.host, this.config.database) + '.db';
144
- var _this = this;
145
- pool[this.identifier] = new sqlite3.Database(file, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE,
146
- function(err) {
147
- if (err) {
148
- _this.error = {
149
- code: err.errno,
150
- message: $.info(err).between('Error: ', ']')
151
- };
152
- } else {
153
- _this.error = undefined;
154
- }
155
- });
156
- }
157
- this.conn = pool[this.identifier];
61
+ Sqlite.prototype._initService = async function() {
62
+ if (this._is_inited) {
63
+ $.log.warn('SQLite服务已初始化');
64
+ return;
65
+ }
66
+
67
+ try {
68
+ $.log.debug('[Sqlite] [_initService]', '初始化SQLite服务', { config: this.config });
69
+ this._is_inited = true;
70
+ $.log.debug('[Sqlite] [_initService]', 'SQLite服务初始化完成');
71
+ } catch (error) {
72
+ $.log.error('[Sqlite] [_initService]', 'SQLite服务初始化失败', { error: error.message });
73
+ throw error;
74
+ }
75
+ };
76
+
77
+ /**
78
+ * 打开数据库连接
79
+ * @param {Number} timeout - 超时时间(毫秒)
80
+ * @returns {Promise<boolean>}
81
+ */
82
+ Sqlite.prototype.open = async function(timeout) {
83
+ if (this._status === 'connected' || this._status === 'connecting') {
84
+ $.log.warn('数据库连接已存在或正在连接中');
85
+ return true;
86
+ }
87
+
88
+ timeout = timeout || this.config.connect_timeout || 10000;
89
+ this._status = 'connecting';
90
+
91
+ try {
92
+ // $.log.debug(`[${this.constructor.name}] [open]`, '开始创建数据库连接', {
93
+ // host: this.config.host,
94
+ // port: this.config.port,
95
+ // database: this.config.database,
96
+ // user: this.config.user,
97
+ // timeout: timeout
98
+ // });
99
+
100
+ // 创建连接
101
+ const connection_promise = this._openInternal();
102
+ const timeout_promise = new Promise((_, reject) => {
103
+ setTimeout(() => {
104
+ reject(new Error(`数据库连接超时(${timeout}ms)`));
105
+ }, timeout);
106
+ });
107
+
108
+ try {
109
+ await Promise.race([connection_promise, timeout_promise]);
110
+
111
+ this._last_connect_time = Date.now();
112
+ this._status = 'connected';
113
+ $.log.info(`[${this.constructor.name}] [open]`, '数据库连接成功', {
114
+ host: this.config.host,
115
+ port: this.config.port,
116
+ database: this.config.database
117
+ });
118
+ return true;
119
+ } catch (connection_err) {
120
+ $.log.error(`[${this.constructor.name}] [open]`, '连接过程错误详情', {
121
+ error: connection_err.message,
122
+ code: connection_err.code,
123
+ syscall: connection_err.syscall,
124
+ address: connection_err.address,
125
+ port: connection_err.port,
126
+ stack: connection_err.stack
127
+ });
128
+ throw connection_err;
129
+ }
130
+ } catch (err) {
131
+ this._status = 'closed';
132
+ $.log.error(`[${this.constructor.name}] [open]`, '数据库连接失败', {
133
+ error: err.message,
134
+ host: this.config.host,
135
+ port: this.config.port,
136
+ database: this.config.database
137
+ });
138
+ throw err;
139
+ }
140
+ };
141
+
142
+ /**
143
+ * 内部连接方法
144
+ * @private
145
+ * @returns {Promise<void>}
146
+ */
147
+ Sqlite.prototype._openInternal = function() {
148
+ return new Promise((resolve, reject) => {
149
+ try {
150
+ const fs = require('fs');
151
+ const path = require('path');
152
+
153
+ // 确保数据库目录存在
154
+ const db_path = this._getDatabasePath();
155
+ const dir = path.dirname(db_path);
156
+
157
+ if (!fs.existsSync(dir)) {
158
+ fs.mkdirSync(dir, { recursive: true });
159
+ }
160
+
161
+ // 创建数据库连接
162
+ this._db = new sqlite3.Database(db_path);
163
+ this._open = true;
164
+ this._conn_retry_count = 0;
165
+
166
+ // 设置连接错误处理
167
+ this._db.on('error', (err) => {
168
+ $.log.error('SQLite数据库连接错误:', err);
169
+ this._handleConnectionError(err);
170
+ });
171
+
172
+ $.log.debug(`SQLite数据库已打开: ${db_path}`);
173
+ resolve();
174
+ } catch (error) {
175
+ reject(error);
176
+ }
177
+ });
158
178
  };
159
179
 
160
180
  /**
161
- * @description 关闭连接
181
+ * 获取数据库路径
182
+ * @private
183
+ * @returns {String}
184
+ */
185
+ Sqlite.prototype._getDatabasePath = function() {
186
+ const db_name = this.config.database || 'mm';
187
+ const db_dir = this.config.host || '/db/';
188
+ return `${db_dir}${db_name}.db`;
189
+ };
190
+
191
+ /**
192
+ * 关闭数据库连接
193
+ * @returns {Promise<boolean>}
162
194
  */
163
195
  Sqlite.prototype.close = function() {
164
- if (pool[this.identifier]) {
165
- pool[this.identifier].close();
166
- pool[this.identifier] = null;
167
- }
196
+ if (this._status !== 'connected') {
197
+ $.log.warn('数据库连接未建立');
198
+ return Promise.resolve(false);
199
+ }
200
+
201
+ return new Promise((resolve) => {
202
+ try {
203
+ if (this._db) {
204
+ $.log.debug('关闭数据库连接');
205
+ this._db.close((err) => {
206
+ if (err) {
207
+ $.log.error('关闭数据库失败', { error: err.message });
208
+ } else {
209
+ $.log.info('数据库已关闭');
210
+ }
211
+ this._db = null;
212
+ this._open = false;
213
+ this._status = 'closed';
214
+ resolve(!err);
215
+ });
216
+ } else {
217
+ this._status = 'closed';
218
+ resolve(true);
219
+ }
220
+ } catch (err) {
221
+ $.log.error('关闭数据库连接时发生异常', { error: err.message });
222
+ this._status = 'closed';
223
+ resolve(false);
224
+ }
225
+ });
168
226
  };
169
227
 
170
228
  /**
171
- * 获取数据库管理器
172
- * @param {String} key 主键
173
- * @param {String|Number} value 对象值
174
- * @param {Boolean} clear_prefix 清除前缀
175
- * @param {Array} arr_table 关联的数据表
176
- * @return {Object} 管理模型
229
+ * 获取数据库连接
230
+ * @param {Number} timeout - 超时时间(毫秒)
231
+ * @returns {Promise<Object>}
177
232
  */
178
- Sqlite.prototype.dbs = async function(key, value, clear_prefix, ...arr_table) {
179
- var lm = new Link_model({
180
- key,
181
- value,
182
- clear_prefix
183
- });
184
- lm.sql = this;
185
- for (var i = 0; i < arr_table.length; i++) {
186
- await lm.add(arr_table[i]);
187
- }
188
- return lm;
233
+ Sqlite.prototype.getConn = async function(timeout) {
234
+ timeout = timeout || this.config.acquire_timeout || this.config.connect_timeout || 20000;
235
+
236
+ // $.log.debug(`[${this.constructor.name}] [getConn] 使用超时时间: ${timeout}ms`);
237
+
238
+ if (this._status !== 'connected') {
239
+ throw new Error('数据库连接未建立');
240
+ }
241
+
242
+ try {
243
+ const connection_promise = new Promise((resolve) => {
244
+ resolve(this._db);
245
+ });
246
+ const timeout_promise = new Promise((_, reject) => {
247
+ setTimeout(() => {
248
+ reject(new Error(`获取数据库连接超时(${timeout}ms)`));
249
+ }, timeout);
250
+ });
251
+
252
+ const conn = await Promise.race([connection_promise, timeout_promise]);
253
+
254
+ // $.log.debug(`[${this.constructor.name}] [getConn] 成功获取数据库连接`);
255
+
256
+ // 处理连接错误
257
+ conn.on('error', (err) => {
258
+ if (err.code && (err.code === 'ECONNRESET' || err.code === 'ETIMEDOUT')) {
259
+ this._handleConnectionError(err);
260
+ }
261
+ });
262
+
263
+ return conn;
264
+ } catch (error) {
265
+ $.log.error(`[${this.constructor.name}] [getConn] 获取连接失败`, {
266
+ error: error.message
267
+ });
268
+
269
+ if (error.code && (error.code === 'ECONNRESET' || error.code === 'ETIMEDOUT')) {
270
+ this._handleConnectionError(error);
271
+ }
272
+
273
+ throw error;
274
+ }
189
275
  };
190
276
 
191
277
  /**
192
- * @description 导出Sqlite帮助类
278
+ * 处理连接错误
279
+ * @private
280
+ * @param {Error} err - 错误对象
193
281
  */
194
- exports.Sqlite = Sqlite;
282
+ Sqlite.prototype._handleConnectionError = function(err) {
283
+ if (this._reconnecting) {
284
+ $.log.debug('重连已在进行中');
285
+ return;
286
+ }
287
+
288
+ if (this.config.enable_reconnect) {
289
+ $.log.info('开始自动重连...');
290
+ this._reconnect(this.config.max_reconnect_attempts || 3)
291
+ .catch(reconnect_err => {
292
+ $.log.error('重连失败', { error: reconnect_err.message });
293
+ this._status = 'closed';
294
+ });
295
+ } else {
296
+ $.log.warn('自动重连已禁用');
297
+ this._status = 'closed';
298
+ }
299
+ };
195
300
 
196
301
  /**
197
- * @description sqlite连接池
302
+ * 重新连接数据库
303
+ * @private
304
+ * @param {Number} max_retries - 最大重试次数
305
+ * @returns {Promise<boolean>}
198
306
  */
307
+ Sqlite.prototype._reconnect = async function(max_retries) {
308
+ if (this._reconnecting) {
309
+ $.log.warn('重连已在进行中');
310
+ return false;
311
+ }
312
+
313
+ this._reconnecting = true;
314
+ let retry_count = 0;
315
+
316
+ try {
317
+ // 先关闭现有连接
318
+ if (this._status === 'connected') {
319
+ await this.close();
320
+ }
321
+
322
+ while (retry_count < max_retries) {
323
+ retry_count++;
324
+ $.log.info(`第${retry_count}/${max_retries}次尝试重连`);
325
+
326
+ try {
327
+ const reconnect_timeout = this.config.connect_timeout || this.config.acquire_timeout || 20000;
328
+ $.log.debug(`重连超时设置为: ${reconnect_timeout}ms`);
329
+ await this.open(reconnect_timeout);
330
+ $.log.info('重连成功');
331
+ return true;
332
+ } catch (err) {
333
+ $.log.error(`重连失败(${retry_count}/${max_retries})`, { error: err.message });
334
+
335
+ if (retry_count < max_retries) {
336
+ const wait_time = this.config.reconnect_interval || 1000;
337
+ $.log.debug(`等待${wait_time}ms后重试`);
338
+ await this._sleep(wait_time);
339
+ }
340
+ }
341
+ }
342
+
343
+ $.log.error(`达到最大重试次数(${max_retries}),重连失败`);
344
+ throw new Error(`重连失败:达到最大重试次数(${max_retries})`);
345
+ } finally {
346
+ this._reconnecting = false;
347
+ }
348
+ };
349
+
350
+ /**
351
+ * 休眠函数
352
+ * @private
353
+ * @param {Number} ms - 休眠时间(毫秒)
354
+ * @returns {Promise<void>}
355
+ */
356
+ Sqlite.prototype._sleep = function(ms) {
357
+ return new Promise(resolve => setTimeout(resolve, ms));
358
+ };
359
+
360
+ /**
361
+ * 执行SQL查询
362
+ * @param {String} sql - SQL语句
363
+ * @param {Array} params - 参数数组
364
+ * @param {Number} timeout - 超时时间(毫秒)
365
+ * @returns {Promise<Object>}
366
+ */
367
+ Sqlite.prototype.run = async function(sql, params, timeout) {
368
+ let conn = null;
369
+ timeout = timeout || this.config.query_timeout || 30000;
370
+
371
+ try {
372
+ // 获取连接
373
+ conn = await this.getConn(timeout);
374
+
375
+ // 直接在方法内部实现超时控制
376
+ const query_promise = new Promise((resolve, reject) => {
377
+ conn.all(sql, params || [], (error, rows) => {
378
+ if (error) {
379
+ reject(error);
380
+ } else {
381
+ // 保持与MySQL兼容的返回值格式
382
+ // 如果是SELECT查询且只有一行结果,返回第一行
383
+ // 否则返回完整结果数组
384
+ if (sql.trim().toUpperCase().startsWith('SELECT') && rows.length === 1) {
385
+ resolve(rows[0]);
386
+ } else {
387
+ resolve(rows);
388
+ }
389
+ }
390
+ });
391
+ });
392
+
393
+ const timeout_promise = new Promise((_, reject) => {
394
+ setTimeout(() => {
395
+ reject(new Error(`SQL查询超时: ${timeout}ms`));
396
+ }, timeout);
397
+ });
398
+
399
+ const result = await Promise.race([query_promise, timeout_promise]);
400
+
401
+ return result;
402
+ } catch (err) {
403
+ $.log.error('[Sqlite] [run]', 'SQL执行失败', {
404
+ error: err.message,
405
+ sql: typeof sql === 'string' ? sql.substring(0, 200) : sql,
406
+ params: params
407
+ });
408
+
409
+ // 处理连接错误,触发重连
410
+ if (err.code && (err.code === 'ECONNRESET' || err.code === 'ETIMEDOUT')) {
411
+ this._handleConnectionError(err);
412
+ }
413
+
414
+ throw err;
415
+ }
416
+ };
417
+
418
+ /**
419
+ * 执行SQL语句(用于执行非查询语句如INSERT/UPDATE/DELETE)
420
+ * @param {String} sql - SQL语句
421
+ * @param {Array} params - 参数数组
422
+ * @param {Number} timeout - 超时时间(毫秒)
423
+ * @returns {Promise<Object>}
424
+ */
425
+ Sqlite.prototype.exec = async function(sql, params, timeout) {
426
+ let conn = null;
427
+ timeout = timeout || this.config.query_timeout || 30000;
428
+
429
+ try {
430
+ // 获取连接
431
+ conn = await this.getConn(timeout);
432
+
433
+ // 直接在方法内部实现超时控制
434
+ const query_promise = new Promise((resolve, reject) => {
435
+ conn.run(sql, params || [], function(error) {
436
+ if (error) {
437
+ reject(error);
438
+ } else {
439
+ // 保持与MySQL兼容的返回值格式
440
+ resolve({
441
+ affected_rows: this.changes || 0,
442
+ insert_id: this.lastID || 0,
443
+ changed_rows: this.changes || 0
444
+ });
445
+ }
446
+ });
447
+ });
448
+
449
+ const timeout_promise = new Promise((_, reject) => {
450
+ setTimeout(() => {
451
+ reject(new Error(`SQL执行超时: ${timeout}ms`));
452
+ }, timeout);
453
+ });
454
+
455
+ const result = await Promise.race([query_promise, timeout_promise]);
456
+
457
+ return result;
458
+ } catch (err) {
459
+ $.log.error('[Sqlite] [exec]', 'SQL执行失败', {
460
+ error: err.message,
461
+ sql: sql.substring(0, 200),
462
+ params: params
463
+ });
464
+
465
+ // 处理连接错误,触发重连
466
+ if (err.code && (err.code === 'ECONNRESET' || err.code === 'ETIMEDOUT')) {
467
+ this._handleConnectionError(err);
468
+ }
469
+
470
+ throw err;
471
+ }
472
+ };
473
+
474
+ /**
475
+ * 读取整张表的数据
476
+ * @param {String} table - 表名
477
+ * @param {Object} condition - 查询条件
478
+ * @param {Object} options - 选项(order_by, limit, offset等)
479
+ * @returns {Promise<Array>}
480
+ */
481
+ Sqlite.prototype.read = async function(table, condition, options) {
482
+ try {
483
+ // 检查连接状态
484
+ if (this._status !== 'connected') {
485
+ throw new Error('数据库连接未建立');
486
+ }
487
+
488
+ // 构建基础SQL查询
489
+ let sql = `SELECT * FROM ${table}`;
490
+ const params = [];
491
+
492
+ // 处理条件
493
+ if (condition && Object.keys(condition).length > 0) {
494
+ const where_clauses = [];
495
+ for (const [field, value] of Object.entries(condition)) {
496
+ where_clauses.push(`${field} = ?`);
497
+ params.push(value);
498
+ }
499
+ sql += ` WHERE ${where_clauses.join(' AND ')}`;
500
+ }
501
+
502
+ // 处理排序
503
+ if (options && options.order_by) {
504
+ sql += ` ORDER BY ${options.order_by}`;
505
+ }
506
+
507
+ // 处理分页
508
+ if (options && options.limit) {
509
+ sql += ` LIMIT ${options.limit}`;
510
+ }
511
+
512
+ if (options && options.offset) {
513
+ sql += ` OFFSET ${options.offset}`;
514
+ }
515
+
516
+ // 记录查询日志
517
+ if (this.config.debug) {
518
+ $.log.debug(`[${this.constructor.name}] [read] 查询数据`, { sql, params });
519
+ }
520
+
521
+ // 执行查询
522
+ const results = await this.run(sql, params);
523
+
524
+ if (this.config.debug) {
525
+ $.log.info(`[${this.constructor.name}] [read] 查询成功`, { count: Array.isArray(results) ? results.length : 1 });
526
+ }
527
+
528
+ // 确保返回数组格式
529
+ return Array.isArray(results) ? results : [results];
530
+ } catch (error) {
531
+ // 记录错误日志
532
+ $.log.error(`[${this.constructor.name}] [read] 查询失败`, {
533
+ error: error.message,
534
+ table: table,
535
+ condition: condition
536
+ });
537
+
538
+ // 抛出错误
539
+ throw error;
540
+ }
541
+ };
542
+
543
+ /**
544
+ * 获取数据库操作实例
545
+ * @param {String} database - 数据库名称
546
+ * @returns {Object} 数据库操作实例
547
+ */
548
+ Sqlite.prototype.db = function(database) {
549
+ if (this._status !== 'connected') {
550
+ throw new Error('数据库连接未建立');
551
+ }
552
+
553
+ // 优化:缓存DB实例,避免重复创建
554
+ if (!this._db_instance) {
555
+ this._db_instance = new DB(this);
556
+
557
+ // 为DB实例添加必要的方法,确保与MySQL接口兼容
558
+ this._db_instance.run = this.run.bind(this);
559
+ this._db_instance.exec = this.exec.bind(this);
560
+ }
561
+
562
+ if (database) {
563
+ this._db_instance.database = database;
564
+ }
565
+
566
+ return this._db_instance;
567
+ };
568
+
569
+ /**
570
+ * 获取数据库管理器模型
571
+ * @returns {Object} 数据库管理器模型
572
+ */
573
+ Sqlite.prototype.dbs = function() {
574
+ return this.db();
575
+ };
576
+
577
+ /**
578
+ * 开始事务
579
+ * @returns {Promise<Object>} 事务连接对象
580
+ */
581
+ Sqlite.prototype.beginTransaction = async function() {
582
+ try {
583
+ // 检查连接状态
584
+ if (this._status !== 'connected') {
585
+ throw new Error('数据库连接未建立');
586
+ }
587
+
588
+ // 获取连接
589
+ const connection = await this.getConn();
590
+
591
+ // 开始事务
592
+ await new Promise((resolve, reject) => {
593
+ connection.run('BEGIN TRANSACTION', (error) => {
594
+ if (error) {
595
+ reject(error);
596
+ } else {
597
+ resolve();
598
+ }
599
+ });
600
+ });
601
+
602
+ if (this.config.debug) {
603
+ $.log.debug(`[${this.constructor.name}] [beginTransaction] 事务开始`);
604
+ }
605
+
606
+ // 返回事务连接对象,包含提交和回滚方法
607
+ return {
608
+ connection,
609
+ commit: async () => {
610
+ await new Promise((resolve, reject) => {
611
+ connection.run('COMMIT', (error) => {
612
+ if (error) {
613
+ reject(error);
614
+ } else {
615
+ resolve();
616
+ }
617
+ });
618
+ });
619
+ if (this.config.debug) {
620
+ $.log.debug(`[${this.constructor.name}] [beginTransaction] 事务提交`);
621
+ }
622
+ },
623
+ rollback: async () => {
624
+ await new Promise((resolve, reject) => {
625
+ connection.run('ROLLBACK', (error) => {
626
+ if (error) {
627
+ reject(error);
628
+ } else {
629
+ resolve();
630
+ }
631
+ });
632
+ });
633
+ if (this.config.debug) {
634
+ $.log.debug(`[${this.constructor.name}] [beginTransaction] 事务回滚`);
635
+ }
636
+ },
637
+ exec: async (sql, params) => {
638
+ // 在事务中执行SQL
639
+ return new Promise((resolve, reject) => {
640
+ connection.run(sql, params || [], function(error) {
641
+ if (error) {
642
+ reject(error);
643
+ } else {
644
+ resolve({
645
+ affected_rows: this.changes,
646
+ insert_id: this.lastID,
647
+ changed_rows: this.changes,
648
+ last_id: this.lastID,
649
+ changes: this.changes
650
+ });
651
+ }
652
+ });
653
+ });
654
+ }
655
+ };
656
+ } catch (error) {
657
+ $.log.error(`[${this.constructor.name}] [beginTransaction] 事务开始失败`, { error: error.message });
658
+ throw error;
659
+ }
660
+ };
661
+
662
+ /**
663
+ * 在事务中执行多个操作
664
+ * @param {Function} callback - 包含事务操作的回调函数
665
+ * @returns {Promise<*>} 回调函数的返回值
666
+ */
667
+ Sqlite.prototype.transaction = async function(callback) {
668
+ let transaction = null;
669
+
670
+ try {
671
+ // 开始事务
672
+ transaction = await this.beginTransaction();
673
+
674
+ // 执行回调函数,传入事务对象
675
+ const result = await callback(transaction);
676
+
677
+ // 提交事务
678
+ await transaction.commit();
679
+
680
+ return result;
681
+ } catch (error) {
682
+ // 如果有事务,回滚
683
+ if (transaction) {
684
+ await transaction.rollback().catch(err => {
685
+ $.log.error(`[${this.constructor.name}] [transaction] 事务回滚失败`, { error: err.message });
686
+ });
687
+ }
688
+
689
+ $.log.error(`[${this.constructor.name}] [transaction] 事务执行失败`, { error: error.message });
690
+ throw error;
691
+ }
692
+ };
693
+
694
+ /**
695
+ * 确保连接池对象存在
696
+ */
697
+ if (!$.pool) {
698
+ $.pool = {};
699
+ }
199
700
  if (!$.pool.sqlite) {
200
701
  $.pool.sqlite = {};
201
702
  }
202
703
 
203
704
  /**
204
- * @description 缓存管理器,用于创建缓存
705
+ * Sqlite管理器,用于创建缓存
205
706
  * @param {String} scope 作用域
206
- * @param {String} dir 当前路径
207
- * @return {Object} 返回一个缓存类
707
+ * @param {Object} config 配置参数
708
+ * @return {Object} 返回一个Sqlite类实例
208
709
  */
209
- function sqlite_admin(scope, dir) {
710
+ function sqliteAdmin(scope, config) {
210
711
  if (!scope) {
211
- scope = $.val.scope
712
+ scope = 'sys';
212
713
  }
213
714
  var obj = $.pool.sqlite[scope];
214
715
  if (!obj) {
215
- $.pool.sqlite[scope] = new Sqlite(scope, dir);
716
+ $.pool.sqlite[scope] = new Sqlite(config);
216
717
  obj = $.pool.sqlite[scope];
217
718
  }
218
719
  return obj;
219
720
  }
220
721
 
221
- /**
222
- * @description 导出Sqlite管理函数
223
- */
224
- exports.sqlite_admin = sqlite_admin;
722
+ // 模块导出
723
+ exports.Sqlite = Sqlite;
724
+ exports.sqliteAdmin = sqliteAdmin;