mm_sqlite 1.1.2 → 1.1.4

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 CHANGED
@@ -1,201 +1,21 @@
1
- Apache License
2
- Version 2.0, January 2004
3
- http://www.apache.org/licenses/
4
-
5
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
-
7
- 1. Definitions.
8
-
9
- "License" shall mean the terms and conditions for use, reproduction,
10
- and distribution as defined by Sections 1 through 9 of this document.
11
-
12
- "Licensor" shall mean the copyright owner or entity authorized by
13
- the copyright owner that is granting the License.
14
-
15
- "Legal Entity" shall mean the union of the acting entity and all
16
- other entities that control, are controlled by, or are under common
17
- control with that entity. For the purposes of this definition,
18
- "control" means (i) the power, direct or indirect, to cause the
19
- direction or management of such entity, whether by contract or
20
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
- outstanding shares, or (iii) beneficial ownership of such entity.
22
-
23
- "You" (or "Your") shall mean an individual or Legal Entity
24
- exercising permissions granted by this License.
25
-
26
- "Source" form shall mean the preferred form for making modifications,
27
- including but not limited to software source code, documentation
28
- source, and configuration files.
29
-
30
- "Object" form shall mean any form resulting from mechanical
31
- transformation or translation of a Source form, including but
32
- not limited to compiled object code, generated documentation,
33
- and conversions to other media types.
34
-
35
- "Work" shall mean the work of authorship, whether in Source or
36
- Object form, made available under the License, as indicated by a
37
- copyright notice that is included in or attached to the work
38
- (an example is provided in the Appendix below).
39
-
40
- "Derivative Works" shall mean any work, whether in Source or Object
41
- form, that is based on (or derived from) the Work and for which the
42
- editorial revisions, annotations, elaborations, or other modifications
43
- represent, as a whole, an original work of authorship. For the purposes
44
- of this License, Derivative Works shall not include works that remain
45
- separable from, or merely link (or bind by name) to the interfaces of,
46
- the Work and Derivative Works thereof.
47
-
48
- "Contribution" shall mean any work of authorship, including
49
- the original version of the Work and any modifications or additions
50
- to that Work or Derivative Works thereof, that is intentionally
51
- submitted to Licensor for inclusion in the Work by the copyright owner
52
- or by an individual or Legal Entity authorized to submit on behalf of
53
- the copyright owner. For the purposes of this definition, "submitted"
54
- means any form of electronic, verbal, or written communication sent
55
- to the Licensor or its representatives, including but not limited to
56
- communication on electronic mailing lists, source code control systems,
57
- and issue tracking systems that are managed by, or on behalf of, the
58
- Licensor for the purpose of discussing and improving the Work, but
59
- excluding communication that is conspicuously marked or otherwise
60
- designated in writing by the copyright owner as "Not a Contribution."
61
-
62
- "Contributor" shall mean Licensor and any individual or Legal Entity
63
- on behalf of whom a Contribution has been received by Licensor and
64
- subsequently incorporated within the Work.
65
-
66
- 2. Grant of Copyright License. Subject to the terms and conditions of
67
- this License, each Contributor hereby grants to You a perpetual,
68
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
- copyright license to reproduce, prepare Derivative Works of,
70
- publicly display, publicly perform, sublicense, and distribute the
71
- Work and such Derivative Works in Source or Object form.
72
-
73
- 3. Grant of Patent License. Subject to the terms and conditions of
74
- this License, each Contributor hereby grants to You a perpetual,
75
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
- (except as stated in this section) patent license to make, have made,
77
- use, offer to sell, sell, import, and otherwise transfer the Work,
78
- where such license applies only to those patent claims licensable
79
- by such Contributor that are necessarily infringed by their
80
- Contribution(s) alone or by combination of their Contribution(s)
81
- with the Work to which such Contribution(s) was submitted. If You
82
- institute patent litigation against any entity (including a
83
- cross-claim or counterclaim in a lawsuit) alleging that the Work
84
- or a Contribution incorporated within the Work constitutes direct
85
- or contributory patent infringement, then any patent licenses
86
- granted to You under this License for that Work shall terminate
87
- as of the date such litigation is filed.
88
-
89
- 4. Redistribution. You may reproduce and distribute copies of the
90
- Work or Derivative Works thereof in any medium, with or without
91
- modifications, and in Source or Object form, provided that You
92
- meet the following conditions:
93
-
94
- (a) You must give any other recipients of the Work or
95
- Derivative Works a copy of this License; and
96
-
97
- (b) You must cause any modified files to carry prominent notices
98
- stating that You changed the files; and
99
-
100
- (c) You must retain, in the Source form of any Derivative Works
101
- that You distribute, all copyright, patent, trademark, and
102
- attribution notices from the Source form of the Work,
103
- excluding those notices that do not pertain to any part of
104
- the Derivative Works; and
105
-
106
- (d) If the Work includes a "NOTICE" text file as part of its
107
- distribution, then any Derivative Works that You distribute must
108
- include a readable copy of the attribution notices contained
109
- within such NOTICE file, excluding those notices that do not
110
- pertain to any part of the Derivative Works, in at least one
111
- of the following places: within a NOTICE text file distributed
112
- as part of the Derivative Works; within the Source form or
113
- documentation, if provided along with the Derivative Works; or,
114
- within a display generated by the Derivative Works, if and
115
- wherever such third-party notices normally appear. The contents
116
- of the NOTICE file are for informational purposes only and
117
- do not modify the License. You may add Your own attribution
118
- notices within Derivative Works that You distribute, alongside
119
- or as an addendum to the NOTICE text from the Work, provided
120
- that such additional attribution notices cannot be construed
121
- as modifying the License.
122
-
123
- You may add Your own copyright statement to Your modifications and
124
- may provide additional or different license terms and conditions
125
- for use, reproduction, or distribution of Your modifications, or
126
- for any such Derivative Works as a whole, provided Your use,
127
- reproduction, and distribution of the Work otherwise complies with
128
- the conditions stated in this License.
129
-
130
- 5. Submission of Contributions. Unless You explicitly state otherwise,
131
- any Contribution intentionally submitted for inclusion in the Work
132
- by You to the Licensor shall be under the terms and conditions of
133
- this License, without any additional terms or conditions.
134
- Notwithstanding the above, nothing herein shall supersede or modify
135
- the terms of any separate license agreement you may have executed
136
- with Licensor regarding such Contributions.
137
-
138
- 6. Trademarks. This License does not grant permission to use the trade
139
- names, trademarks, service marks, or product names of the Licensor,
140
- except as required for reasonable and customary use in describing the
141
- origin of the Work and reproducing the content of the NOTICE file.
142
-
143
- 7. Disclaimer of Warranty. Unless required by applicable law or
144
- agreed to in writing, Licensor provides the Work (and each
145
- Contributor provides its Contributions) on an "AS IS" BASIS,
146
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
- implied, including, without limitation, any warranties or conditions
148
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
- PARTICULAR PURPOSE. You are solely responsible for determining the
150
- appropriateness of using or redistributing the Work and assume any
151
- risks associated with Your exercise of permissions under this License.
152
-
153
- 8. Limitation of Liability. In no event and under no legal theory,
154
- whether in tort (including negligence), contract, or otherwise,
155
- unless required by applicable law (such as deliberate and grossly
156
- negligent acts) or agreed to in writing, shall any Contributor be
157
- liable to You for damages, including any direct, indirect, special,
158
- incidental, or consequential damages of any character arising as a
159
- result of this License or out of the use or inability to use the
160
- Work (including but not limited to damages for loss of goodwill,
161
- work stoppage, computer failure or malfunction, or any and all
162
- other commercial damages or losses), even if such Contributor
163
- has been advised of the possibility of such damages.
164
-
165
- 9. Accepting Warranty or Additional Liability. While redistributing
166
- the Work or Derivative Works thereof, You may choose to offer,
167
- and charge a fee for, acceptance of support, warranty, indemnity,
168
- or other liability obligations and/or rights consistent with this
169
- License. However, in accepting such obligations, You may act only
170
- on Your own behalf and on Your sole responsibility, not on behalf
171
- of any other Contributor, and only if You agree to indemnify,
172
- defend, and hold each Contributor harmless for any liability
173
- incurred by, or claims asserted against, such Contributor by reason
174
- of your accepting any such warranty or additional liability.
175
-
176
- END OF TERMS AND CONDITIONS
177
-
178
- APPENDIX: How to apply the Apache License to your work.
179
-
180
- To apply the Apache License to your work, attach the following
181
- boilerplate notice, with the fields enclosed by brackets "[]"
182
- replaced with your own identifying information. (Don't include
183
- the brackets!) The text should be enclosed in the appropriate
184
- comment syntax for the file format. We also recommend that a
185
- file or class name and description of purpose be included on the
186
- same "printed page" as the copyright notice for easier
187
- identification within third-party archives.
188
-
189
- Copyright [yyyy] [name of copyright owner]
190
-
191
- Licensed under the Apache License, Version 2.0 (the "License");
192
- you may not use this file except in compliance with the License.
193
- You may obtain a copy of the License at
194
-
195
- http://www.apache.org/licenses/LICENSE-2.0
196
-
197
- Unless required by applicable law or agreed to in writing, software
198
- distributed under the License is distributed on an "AS IS" BASIS,
199
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
- See the License for the specific language governing permissions and
201
- limitations under the License.
1
+ MIT License
2
+
3
+ Copyright (c) 2024 邱文武
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  高性能SQLite数据库操作模块,提供与mm_mysql完全兼容的API接口。适用于Node.js应用的轻量级数据存储解决方案。
4
4
 
5
+ [![npm version](https://img.shields.io/npm/v/mm_sqlite.svg?style=flat-square)](https://www.npmjs.com/package/mm_sqlite)
6
+ [![npm downloads](https://img.shields.io/npm/dm/mm_sqlite.svg?style=flat-square)](https://www.npmjs.com/package/mm_sqlite)
7
+ [![node version](https://img.shields.io/node/v/mm_sqlite.svg?style=flat-square)](https://nodejs.org/en/)
8
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE)
9
+
5
10
  ## 特性
6
11
 
7
12
  - 🚀 **高性能优化**:经过深度优化的SQL构建器和连接管理
@@ -13,18 +18,21 @@
13
18
 
14
19
  ## 安装
15
20
 
16
- 通过npm安装模块:
17
-
21
+ ### 使用 npm
18
22
  ```bash
19
23
  npm install mm_sqlite --save
20
24
  ```
21
25
 
22
- 通过yarn安装模块:
23
-
26
+ ### 使用 yarn
24
27
  ```bash
25
28
  yarn add mm_sqlite
26
29
  ```
27
30
 
31
+ ### 使用 pnpm
32
+ ```bash
33
+ pnpm add mm_sqlite
34
+ ```
35
+
28
36
  ## 依赖要求
29
37
 
30
38
  - Node.js 14.0+
@@ -41,11 +49,12 @@ const { Sqlite } = require('mm_sqlite');
41
49
 
42
50
  // 创建数据库实例
43
51
  const sqlite = new Sqlite({
44
- database: './data/test.db', // 数据库文件路径
45
- timeout: 30000, // 查询超时时间(毫秒)
46
- retry_count: 3, // 失败重试次数
47
- conn_timeout: 30000, // 连接超时时间(毫秒)
48
- enablePerformanceLog: false // 是否启用性能日志
52
+ dir: './db/', // 数据库文件存储目录
53
+ database: 'test', // 数据库文件名(不包含扩展名)
54
+ timeout: 30000, // 查询超时时间(毫秒)
55
+ retry_count: 3, // 失败重试次数
56
+ conn_timeout: 30000, // 连接超时时间(毫秒)
57
+ enablePerformanceLog: false // 是否启用性能日志
49
58
  });
50
59
 
51
60
  // 打开数据库连接
@@ -165,14 +174,14 @@ await sqlite.beginTransaction();
165
174
 
166
175
  try {
167
176
  // 插入数据
168
- await sqlite.table('users').insert({
177
+ await sqlite.table('users').add({
169
178
  name: '张三',
170
179
  email: 'zhangsan@example.com',
171
180
  status: 'active'
172
181
  });
173
182
 
174
- // 更新数据
175
- await sqlite.table('profiles').insert({
183
+ // 插入关联数据
184
+ await sqlite.table('profiles').add({
176
185
  user_id: 1,
177
186
  bio: '这是一个测试用户'
178
187
  });
@@ -242,21 +251,27 @@ const users = await sqlite
242
251
  new Sqlite(config)
243
252
  ```
244
253
 
245
- **参数:**
246
- - `config.database` - 数据库文件路径,默认为`'./db.sqlite'`
254
+ **配置参数:**
255
+ - `config.dir` - 数据库文件存储目录,默认为`'./db/'`
256
+ - `config.database` - 数据库文件名,默认为`'mm'`
247
257
  - `config.timeout` - 查询超时时间,默认`30000ms`
248
258
  - `config.retry_count` - 失败重试次数,默认`3`
249
259
  - `config.conn_timeout` - 连接超时时间,默认`30000ms`
250
- - `config.enablePerformanceLog` - 是否启用性能日志,默认false
260
+ - `config.enablePerformanceLog` - 是否启用性能日志,默认`false`
261
+ - `config.debug` - 是否启用调试模式,默认`false`
251
262
 
252
263
  #### 主要方法
253
264
 
254
- - `getConnection()` - 获取数据库连接,返回Promise<Connection>
255
- - `closeConnection(conn)` - 关闭数据库连接,返回Promise<Boolean>
256
- - `run(sql, params)` - 执行SQL语句(非查询操作),返回Promise<Object>
257
- - `exec(sql, params)` - 执行SQL查询,返回Promise<Array>
258
- - `transaction(fn)` - 执行事务,返回Promise<any>
259
- - `table(tableName)` - 设置表名,返回Sql实例
265
+ - `open(timeout)` - 打开数据库连接,返回`Promise<Boolean>`
266
+ - `close()` - 关闭数据库连接,返回`Promise<Boolean>`
267
+ - `getConn(timeout)` - 获取数据库连接,返回`Promise<Connection>`
268
+ - `run(sql, params, timeout)` - 执行SQL语句(非查询操作),返回`Promise<Object>`
269
+ - `exec(sql, params, timeout)` - 执行SQL查询,返回`Promise<Array>`
270
+ - `beginTransaction()` - 开始事务,返回`Promise<void>`
271
+ - `commit()` - 提交事务,返回`Promise<void>`
272
+ - `rollback()` - 回滚事务,返回`Promise<void>`
273
+ - `transaction(fn)` - 执行事务,返回`Promise<any>`
274
+ - `table(tableName)` - 设置表名,返回`Sql`实例
260
275
 
261
276
  ### Sql类
262
277
 
@@ -339,6 +354,12 @@ A: 可以使用相对路径或绝对路径。建议使用绝对路径以避免
339
354
  **Q: 事务处理是否支持嵌套?**
340
355
  A: 目前不支持嵌套事务,但可以在一个事务中执行多个操作。
341
356
 
357
+ **Q: 如何启用调试模式?**
358
+ A: 在创建Sqlite实例时,设置`debug: true`配置项即可启用调试模式。
359
+
360
+ **Q: 如何处理SQLite的锁问题?**
361
+ A: 避免长时间运行的事务,使用适当的事务隔离级别,并确保在操作完成后及时提交或回滚事务。
362
+
342
363
  ## 许可证
343
364
 
344
365
  MIT License
@@ -350,3 +371,13 @@ MIT License
350
371
  1. 运行测试确保功能正常
351
372
  2. 添加适当的注释和文档
352
373
  3. 遵循项目的代码风格
374
+ 4. 确保代码符合ES6+标准
375
+ 5. 提交前请先拉取最新代码,解决冲突
376
+
377
+ ### 开发流程
378
+
379
+ 1. Fork 仓库
380
+ 2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
381
+ 3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
382
+ 4. 推送到分支 (`git push origin feature/AmazingFeature`)
383
+ 5. 打开 Pull Request
package/db.js CHANGED
@@ -896,4 +896,41 @@ DB.prototype.backup = function(table, backup, timeout = 60000) {
896
896
  }
897
897
  };
898
898
 
899
+ /**
900
+ * @description 创建表
901
+ * @param {String} table 表名
902
+ * @param {Object} model 表模型,键值对,根据值类型创建字段类型,根据键名创建字段名
903
+ * @param {String} key 主键
904
+ * @return {Promise|Number} 操作结果
905
+ */
906
+ DB.prototype.createTable = function(table, model, key = 'id', timeout = 15000){
907
+ if (!table || !model || !model.fields) {
908
+ $.log.error("[DB] [createTable] 参数不完整");
909
+ return 0;
910
+ }
911
+ var fields = '';
912
+ for (const field in model.fields) {
913
+ const value = model.fields[field];
914
+ let type = '';
915
+ if (field === key) {
916
+ type = 'INTEGER PRIMARY KEY AUTOINCREMENT';
917
+ } else if (typeof value === 'number') {
918
+ if (value % 1 === 0) {
919
+ type = 'INTEGER';
920
+ } else {
921
+ type = 'REAL';
922
+ }
923
+ } else if (typeof value === 'string') {
924
+ type = 'TEXT';
925
+ }
926
+ else {
927
+ type = 'BLOB';
928
+ }
929
+ fields += `\`${field}\` ${type}, `;
930
+ }
931
+ fields = fields.slice(0, -2);
932
+ var sql = `CREATE TABLE IF NOT EXISTS \`${table}\` (${fields});`;
933
+ return this.exec(sql, [], timeout);
934
+ }
935
+
899
936
  module.exports = DB;
package/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  const sqlite3 = require('sqlite3').verbose();
2
2
  const DB = require('./db');
3
3
  const { BaseService } = require('mm_base_service');
4
-
5
4
  /**
6
5
  * SQLite数据库操作类
7
6
  * @class Sqlite
@@ -12,8 +11,7 @@ class Sqlite extends BaseService {
12
11
  * 默认配置
13
12
  */
14
13
  static default_config = {
15
- host: "/db/".fullname(),
16
- port: 3306,
14
+ dir: "./db/".fullname(),
17
15
  user: "root",
18
16
  password: "",
19
17
  database: "mm",
@@ -39,7 +37,7 @@ class Sqlite extends BaseService {
39
37
  constructor(config) {
40
38
  const merged_config = Object.assign({}, Sqlite.default_config, config || {});
41
39
  super(merged_config);
42
-
40
+
43
41
  this.config = merged_config;
44
42
  this._connection = null;
45
43
  this._pool = null;
@@ -58,7 +56,7 @@ class Sqlite extends BaseService {
58
56
  * 初始化服务
59
57
  * @returns {Promise<void>}
60
58
  */
61
- Sqlite.prototype._initService = async function() {
59
+ Sqlite.prototype._initService = async function () {
62
60
  if (this._is_inited) {
63
61
  $.log.warn('SQLite服务已初始化');
64
62
  return;
@@ -79,7 +77,7 @@ Sqlite.prototype._initService = async function() {
79
77
  * @param {Number} timeout - 超时时间(毫秒)
80
78
  * @returns {Promise<boolean>}
81
79
  */
82
- Sqlite.prototype.open = async function(timeout) {
80
+ Sqlite.prototype.open = async function (timeout) {
83
81
  if (this._status === 'connected' || this._status === 'connecting') {
84
82
  $.log.warn('数据库连接已存在或正在连接中');
85
83
  return true;
@@ -89,14 +87,6 @@ Sqlite.prototype.open = async function(timeout) {
89
87
  this._status = 'connecting';
90
88
 
91
89
  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
90
  // 创建连接
101
91
  const connection_promise = this._openInternal();
102
92
  const timeout_promise = new Promise((_, reject) => {
@@ -111,8 +101,7 @@ Sqlite.prototype.open = async function(timeout) {
111
101
  this._last_connect_time = Date.now();
112
102
  this._status = 'connected';
113
103
  $.log.info(`[${this.constructor.name}] [open]`, '数据库连接成功', {
114
- host: this.config.host,
115
- port: this.config.port,
104
+ dir: this.config.dir,
116
105
  database: this.config.database
117
106
  });
118
107
  return true;
@@ -122,7 +111,7 @@ Sqlite.prototype.open = async function(timeout) {
122
111
  code: connection_err.code,
123
112
  syscall: connection_err.syscall,
124
113
  address: connection_err.address,
125
- port: connection_err.port,
114
+ dir: connection_err.dir,
126
115
  stack: connection_err.stack
127
116
  });
128
117
  throw connection_err;
@@ -131,8 +120,7 @@ Sqlite.prototype.open = async function(timeout) {
131
120
  this._status = 'closed';
132
121
  $.log.error(`[${this.constructor.name}] [open]`, '数据库连接失败', {
133
122
  error: err.message,
134
- host: this.config.host,
135
- port: this.config.port,
123
+ dir: this.config.dir,
136
124
  database: this.config.database
137
125
  });
138
126
  throw err;
@@ -144,32 +132,29 @@ Sqlite.prototype.open = async function(timeout) {
144
132
  * @private
145
133
  * @returns {Promise<void>}
146
134
  */
147
- Sqlite.prototype._openInternal = function() {
135
+ Sqlite.prototype._openInternal = function () {
148
136
  return new Promise((resolve, reject) => {
149
137
  try {
150
- const fs = require('fs');
151
- const path = require('path');
152
-
138
+
153
139
  // 确保数据库目录存在
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 });
140
+ const file = this._getDatabasePath();
141
+
142
+ if (!file.hasDir()) {
143
+ file.addDir();
159
144
  }
160
-
145
+
161
146
  // 创建数据库连接
162
- this._db = new sqlite3.Database(db_path);
147
+ this._db = new sqlite3.Database(file);
163
148
  this._open = true;
164
149
  this._conn_retry_count = 0;
165
-
150
+
166
151
  // 设置连接错误处理
167
152
  this._db.on('error', (err) => {
168
153
  $.log.error('SQLite数据库连接错误:', err);
169
154
  this._handleConnectionError(err);
170
155
  });
171
-
172
- $.log.debug(`SQLite数据库已打开: ${db_path}`);
156
+
157
+ $.log.debug(`SQLite数据库已打开: ${file}`);
173
158
  resolve();
174
159
  } catch (error) {
175
160
  reject(error);
@@ -182,17 +167,20 @@ Sqlite.prototype._openInternal = function() {
182
167
  * @private
183
168
  * @returns {String}
184
169
  */
185
- Sqlite.prototype._getDatabasePath = function() {
170
+ Sqlite.prototype._getDatabasePath = function () {
186
171
  const db_name = this.config.database || 'mm';
187
- const db_dir = this.config.host || '/db/';
188
- return `${db_dir}${db_name}.db`;
172
+ if (db_name.endsWith('.db')) {
173
+ db_name = db_name.replace('.db', '');
174
+ }
175
+ const db_dir = this.config.dir || '/db/'.fullname();
176
+ return `./${db_name}.db`.fullname(db_dir);
189
177
  };
190
178
 
191
179
  /**
192
180
  * 关闭数据库连接
193
181
  * @returns {Promise<boolean>}
194
182
  */
195
- Sqlite.prototype.close = function() {
183
+ Sqlite.prototype.close = function () {
196
184
  if (this._status !== 'connected') {
197
185
  $.log.warn('数据库连接未建立');
198
186
  return Promise.resolve(false);
@@ -230,7 +218,7 @@ Sqlite.prototype.close = function() {
230
218
  * @param {Number} timeout - 超时时间(毫秒)
231
219
  * @returns {Promise<Object>}
232
220
  */
233
- Sqlite.prototype.getConn = async function(timeout) {
221
+ Sqlite.prototype.getConn = async function (timeout) {
234
222
  timeout = timeout || this.config.acquire_timeout || this.config.connect_timeout || 20000;
235
223
 
236
224
  // $.log.debug(`[${this.constructor.name}] [getConn] 使用超时时间: ${timeout}ms`);
@@ -279,7 +267,7 @@ Sqlite.prototype.getConn = async function(timeout) {
279
267
  * @private
280
268
  * @param {Error} err - 错误对象
281
269
  */
282
- Sqlite.prototype._handleConnectionError = function(err) {
270
+ Sqlite.prototype._handleConnectionError = function (err) {
283
271
  if (this._reconnecting) {
284
272
  $.log.debug('重连已在进行中');
285
273
  return;
@@ -304,7 +292,7 @@ Sqlite.prototype._handleConnectionError = function(err) {
304
292
  * @param {Number} max_retries - 最大重试次数
305
293
  * @returns {Promise<boolean>}
306
294
  */
307
- Sqlite.prototype._reconnect = async function(max_retries) {
295
+ Sqlite.prototype._reconnect = async function (max_retries) {
308
296
  if (this._reconnecting) {
309
297
  $.log.warn('重连已在进行中');
310
298
  return false;
@@ -353,7 +341,7 @@ Sqlite.prototype._reconnect = async function(max_retries) {
353
341
  * @param {Number} ms - 休眠时间(毫秒)
354
342
  * @returns {Promise<void>}
355
343
  */
356
- Sqlite.prototype._sleep = function(ms) {
344
+ Sqlite.prototype._sleep = function (ms) {
357
345
  return new Promise(resolve => setTimeout(resolve, ms));
358
346
  };
359
347
 
@@ -364,7 +352,7 @@ Sqlite.prototype._sleep = function(ms) {
364
352
  * @param {Number} timeout - 超时时间(毫秒)
365
353
  * @returns {Promise<Object>}
366
354
  */
367
- Sqlite.prototype.run = async function(sql, params, timeout) {
355
+ Sqlite.prototype.run = async function (sql, params, timeout) {
368
356
  let conn = null;
369
357
  timeout = timeout || this.config.query_timeout || 30000;
370
358
 
@@ -383,7 +371,7 @@ Sqlite.prototype.run = async function(sql, params, timeout) {
383
371
  }
384
372
  });
385
373
  });
386
-
374
+
387
375
  const timeout_promise = new Promise((_, reject) => {
388
376
  setTimeout(() => {
389
377
  reject(new Error(`SQL查询超时: ${timeout}ms`));
@@ -416,7 +404,7 @@ Sqlite.prototype.run = async function(sql, params, timeout) {
416
404
  * @param {Number} timeout - 超时时间(毫秒)
417
405
  * @returns {Promise<Object>}
418
406
  */
419
- Sqlite.prototype.exec = async function(sql, params, timeout) {
407
+ Sqlite.prototype.exec = async function (sql, params, timeout) {
420
408
  let conn = null;
421
409
  timeout = timeout || this.config.query_timeout || 30000;
422
410
 
@@ -426,7 +414,7 @@ Sqlite.prototype.exec = async function(sql, params, timeout) {
426
414
 
427
415
  // 直接在方法内部实现超时控制
428
416
  const query_promise = new Promise((resolve, reject) => {
429
- conn.run(sql, params || [], function(error) {
417
+ conn.run(sql, params || [], function (error) {
430
418
  if (error) {
431
419
  reject(error);
432
420
  } else {
@@ -439,7 +427,7 @@ Sqlite.prototype.exec = async function(sql, params, timeout) {
439
427
  }
440
428
  });
441
429
  });
442
-
430
+
443
431
  const timeout_promise = new Promise((_, reject) => {
444
432
  setTimeout(() => {
445
433
  reject(new Error(`SQL执行超时: ${timeout}ms`));
@@ -472,7 +460,7 @@ Sqlite.prototype.exec = async function(sql, params, timeout) {
472
460
  * @param {Object} options - 选项(order_by, limit, offset等)
473
461
  * @returns {Promise<Array>}
474
462
  */
475
- Sqlite.prototype.read = async function(table, condition, options) {
463
+ Sqlite.prototype.read = async function (table, condition, options) {
476
464
  try {
477
465
  // 检查连接状态
478
466
  if (this._status !== 'connected') {
@@ -539,24 +527,24 @@ Sqlite.prototype.read = async function(table, condition, options) {
539
527
  * @param {String} database - 数据库名称
540
528
  * @returns {Object} 数据库操作实例
541
529
  */
542
- Sqlite.prototype.db = function(database) {
530
+ Sqlite.prototype.db = function (database) {
543
531
  if (this._status !== 'connected') {
544
532
  throw new Error('数据库连接未建立');
545
533
  }
546
-
534
+
547
535
  // 优化:缓存DB实例,避免重复创建
548
536
  if (!this._db_instance) {
549
537
  this._db_instance = new DB(this);
550
-
538
+
551
539
  // 为DB实例添加必要的方法,确保与MySQL接口兼容
552
540
  this._db_instance.run = this.run.bind(this);
553
541
  this._db_instance.exec = this.exec.bind(this);
554
542
  }
555
-
543
+
556
544
  if (database) {
557
545
  this._db_instance.database = database;
558
546
  }
559
-
547
+
560
548
  return this._db_instance;
561
549
  };
562
550
 
@@ -564,7 +552,7 @@ Sqlite.prototype.db = function(database) {
564
552
  * 获取数据库管理器模型
565
553
  * @returns {Object} 数据库管理器模型
566
554
  */
567
- Sqlite.prototype.dbs = function() {
555
+ Sqlite.prototype.dbs = function () {
568
556
  return this.db();
569
557
  };
570
558
 
@@ -572,7 +560,7 @@ Sqlite.prototype.dbs = function() {
572
560
  * 开始事务
573
561
  * @returns {Promise<Object>} 事务连接对象
574
562
  */
575
- Sqlite.prototype.beginTransaction = async function() {
563
+ Sqlite.prototype.beginTransaction = async function () {
576
564
  try {
577
565
  // 检查连接状态
578
566
  if (this._status !== 'connected') {
@@ -631,7 +619,7 @@ Sqlite.prototype.beginTransaction = async function() {
631
619
  exec: async (sql, params) => {
632
620
  // 在事务中执行SQL
633
621
  return new Promise((resolve, reject) => {
634
- connection.run(sql, params || [], function(error) {
622
+ connection.run(sql, params || [], function (error) {
635
623
  if (error) {
636
624
  reject(error);
637
625
  } else {
@@ -658,7 +646,7 @@ Sqlite.prototype.beginTransaction = async function() {
658
646
  * @param {Function} callback - 包含事务操作的回调函数
659
647
  * @returns {Promise<*>} 回调函数的返回值
660
648
  */
661
- Sqlite.prototype.transaction = async function(callback) {
649
+ Sqlite.prototype.transaction = async function (callback) {
662
650
  let transaction = null;
663
651
 
664
652
  try {
@@ -685,14 +673,31 @@ Sqlite.prototype.transaction = async function(callback) {
685
673
  }
686
674
  };
687
675
 
676
+ /**
677
+ * 设置当前操作的表名
678
+ * @param {String} name - 表名
679
+ * @param {String} key - 主键
680
+ * @returns {Object} 数据库操作实例
681
+ */
682
+ Sqlite.prototype.table = function (name, key) {
683
+ var db = this.db();
684
+ db.table = name;
685
+ if (key) {
686
+ db.key = key;
687
+ }
688
+ return db;
689
+ };
690
+
691
+ // close 方法已在文件前面部分实现,这里不再重复
692
+
688
693
  /**
689
694
  * 确保连接池对象存在
690
695
  */
691
696
  if (!$.pool) {
692
- $.pool = {};
697
+ $.pool = {};
693
698
  }
694
699
  if (!$.pool.sqlite) {
695
- $.pool.sqlite = {};
700
+ $.pool.sqlite = {};
696
701
  }
697
702
 
698
703
  /**
@@ -702,15 +707,15 @@ if (!$.pool.sqlite) {
702
707
  * @return {Object} 返回一个Sqlite类实例
703
708
  */
704
709
  function sqliteAdmin(scope, config) {
705
- if (!scope) {
706
- scope = 'sys';
707
- }
708
- var obj = $.pool.sqlite[scope];
709
- if (!obj) {
710
- $.pool.sqlite[scope] = new Sqlite(config);
711
- obj = $.pool.sqlite[scope];
712
- }
713
- return obj;
710
+ if (!scope) {
711
+ scope = 'sys';
712
+ }
713
+ var obj = $.pool.sqlite[scope];
714
+ if (!obj) {
715
+ $.pool.sqlite[scope] = new Sqlite(config);
716
+ obj = $.pool.sqlite[scope];
717
+ }
718
+ return obj;
714
719
  }
715
720
 
716
721
  // 模块导出
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_sqlite",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "高性能SQLite数据库操作模块,提供与mm_mysql完全兼容的API接口,支持异步操作、事务处理和批量操作",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -36,7 +36,7 @@
36
36
  "node": ">=14.0.0"
37
37
  },
38
38
  "dependencies": {
39
- "mm_logs": "^1.5.4",
39
+ "mm_base_service": "^1.0.2",
40
40
  "sqlite3": "^5.1.7",
41
41
  "sqlstring": "^2.3.3"
42
42
  }
package/config.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "host": "localhost",
3
- "port": 3306,
4
- "user": "root",
5
- "password": "asd159357",
6
- "database": "mm",
7
- "multipleStatements": true
8
- }
Binary file
package/db/mm.db DELETED
Binary file
package/test.js DELETED
@@ -1,81 +0,0 @@
1
- const Sqlite = require('./index.js').Sqlite;
2
-
3
- // 全面测试函数
4
- async function runAllTests() {
5
- $.log.info('开始全面测试mm_sqlite模块...');
6
- var sql = new Sqlite();
7
- await sql.open();
8
-
9
- var test_table = 'test_mm_sqlite';
10
-
11
- try {
12
- // 1. 测试表创建
13
- $.log.info('1. 测试表创建...');
14
- let create_sql = `CREATE TABLE IF NOT EXISTS ${test_table} (
15
- uid INTEGER PRIMARY KEY AUTOINCREMENT,
16
- username VARCHAR(50) NOT NULL,
17
- age INTEGER DEFAULT 0,
18
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
19
- )`;
20
- let create_result = await sql.run(create_sql);
21
- $.log.info('表创建结果:', create_result);
22
-
23
- // 2. 测试数据插入
24
- $.log.info('2. 测试数据插入...');
25
- let insert_sql = `INSERT INTO ${test_table} (username, age) VALUES (?, ?)`;
26
- let insert_result = await sql.run(insert_sql, ['test_user_1', 25]);
27
- $.log.info('插入结果:', insert_result);
28
-
29
- // 3. 测试查询 - 使用exec方法并安全处理返回结果
30
- $.log.info('3. 测试查询...');
31
- let query_sql = `SELECT * FROM ${test_table}`;
32
- let query_result = await sql.exec(query_sql);
33
- $.log.info('查询结果类型:', typeof query_result);
34
- $.log.info('查询结果:', query_result);
35
-
36
- // 4. 测试更新
37
- $.log.info('4. 测试更新...');
38
- let update_sql = `UPDATE ${test_table} SET age = ? WHERE username = ?`;
39
- let update_result = await sql.run(update_sql, [26, 'test_user_1']);
40
- $.log.info('更新结果:', update_result);
41
-
42
- // 5. 测试删除
43
- $.log.info('5. 测试删除...');
44
- let delete_sql = `DELETE FROM ${test_table} WHERE username = ?`;
45
- let delete_result = await sql.run(delete_sql, ['test_user_1']);
46
- $.log.info('删除结果:', delete_result);
47
-
48
- // 6. 测试事务
49
- $.log.info('6. 测试事务...');
50
- let transaction_result = await sql.transaction(async () => {
51
- await sql.run(`INSERT INTO ${test_table} (username, age) VALUES (?, ?)`, ['transaction_user', 40]);
52
- return await sql.run(`DELETE FROM ${test_table} WHERE username = ?`, ['transaction_user']);
53
- });
54
- $.log.info('事务结果:', transaction_result);
55
-
56
- // 7. 测试表列表 - 安全处理exec返回结果
57
- $.log.info('7. 测试表列表...');
58
- let tables_sql = `SELECT name FROM sqlite_master WHERE type='table'`;
59
- let tables_result = await sql.exec(tables_sql);
60
- $.log.info('表列表类型:', typeof tables_result);
61
- $.log.info('表列表:', tables_result);
62
-
63
- // 8. 清理测试表
64
- $.log.info('8. 清理测试表...');
65
- let drop_result = await sql.run(`DROP TABLE IF EXISTS ${test_table}`);
66
- $.log.info('删除表结果:', drop_result);
67
-
68
- $.log.info('所有测试完成!mm_sqlite模块功能正常。');
69
- return true;
70
- } catch (error) {
71
- $.log.error('测试过程中发生错误:', error);
72
- return false;
73
- } finally {
74
- await sql.close();
75
- }
76
- }
77
-
78
- // 运行测试
79
- (async function() {
80
- await runAllTests();
81
- })();
@@ -1,115 +0,0 @@
1
- // 核心方法测试脚本 - 专注测试del、delList等关键方法
2
- const { Sqlite } = require('./index');
3
-
4
- async function testAllMethods() {
5
- try {
6
- console.log('=== 开始测试 SQLite 模块核心方法 ===');
7
-
8
- // 初始化SQLite实例
9
- const sql = new Sqlite({
10
- database: './db/test_core_methods.db'
11
- });
12
-
13
- await sql.open();
14
- console.log('数据库连接成功');
15
-
16
- // 获取数据库操作实例
17
- const db = sql.db();
18
- const test_table = 'test_core_methods';
19
-
20
- // 准备测试表
21
- console.log('\n=== 1. 准备测试环境 ===');
22
- await db.exec(`DROP TABLE IF EXISTS ${test_table};`);
23
- await db.exec(`CREATE TABLE IF NOT EXISTS ${test_table} (
24
- id INTEGER PRIMARY KEY AUTOINCREMENT,
25
- username VARCHAR(50) NOT NULL,
26
- email VARCHAR(100),
27
- age INTEGER DEFAULT 0 NOT NULL
28
- );`);
29
- console.log('测试表创建完成');
30
-
31
- db.table = test_table;
32
-
33
- // 2. 单条数据操作测试
34
- console.log('\n=== 2. 单条数据操作测试 ===');
35
- // 添加单条数据
36
- const addResult = await db.add({
37
- username: 'test_user1',
38
- email: 'test1@example.com',
39
- age: 25
40
- });
41
- console.log('✓ add方法测试通过:', addResult);
42
-
43
- // 查询单条数据
44
- const getResult = await db.get({ username: 'test_user1' });
45
- console.log('✓ get方法测试通过,数据:', getResult[0]?.username);
46
-
47
- // 修改数据
48
- const setResult = await db.set(
49
- { username: 'test_user1' },
50
- { age: 26 }
51
- );
52
- console.log('✓ set方法测试通过:', setResult);
53
-
54
- // 3. 批量操作测试 - 重点测试addList
55
- console.log('\n=== 3. 批量添加测试 ===');
56
- const batchData = [
57
- { username: 'batch_user1', email: 'batch1@example.com', age: 30 },
58
- { username: 'batch_user2', email: 'batch2@example.com', age: 31 },
59
- { username: 'batch_user3', email: 'batch3@example.com', age: 32 }
60
- ];
61
-
62
- const addListResult = await db.addList(batchData);
63
- console.log('✓ addList方法测试通过:', addListResult);
64
-
65
- // 4. 单条删除测试 - 重点测试del
66
- console.log('\n=== 4. 单条删除测试 ===');
67
- const delResult = await db.del({ username: 'test_user1' });
68
- console.log('✓ del方法测试通过:', delResult);
69
-
70
- // 验证删除结果
71
- const delCheck = await db.get({ username: 'test_user1' });
72
- console.log(' del方法验证结果: 删除成功', delCheck.length === 0);
73
-
74
- // 5. 批量删除测试 - 重点测试delList
75
- console.log('\n=== 5. 批量删除测试 ===');
76
- const deleteList = [
77
- { query: { username: 'batch_user1' } },
78
- { query: { username: 'batch_user2' } }
79
- ];
80
-
81
- const delListResult = await db.delList(deleteList);
82
- console.log('✓ delList方法测试通过:', delListResult);
83
-
84
- // 验证批量删除结果
85
- const batch1Check = await db.get({ username: 'batch_user1' });
86
- const batch2Check = await db.get({ username: 'batch_user2' });
87
- console.log(' delList方法验证结果: 批量删除成功',
88
- batch1Check.length === 0 && batch2Check.length === 0);
89
-
90
- // 验证剩余数据
91
- const remainingData = await db.get({});
92
- console.log(' 剩余数据数量:', remainingData.length);
93
-
94
- // 6. 清理测试数据
95
- console.log('\n=== 6. 清理测试环境 ===');
96
- await db.exec(`DROP TABLE IF EXISTS ${test_table};`);
97
- console.log('测试表清理完成');
98
-
99
- // 关闭数据库连接
100
- await sql.close();
101
- console.log('\n=== 核心方法测试完成!===');
102
- console.log('✓ del方法工作正常');
103
- console.log('✓ delList方法工作正常');
104
- console.log('✓ 其他核心方法(add, get, set, addList)工作正常');
105
-
106
- } catch (error) {
107
- console.error('测试过程中出现错误:', error.message);
108
- console.error('错误堆栈:', error.stack);
109
- }
110
- }
111
-
112
- // 执行测试
113
- (async () => {
114
- await testAllMethods();
115
- })();
@@ -1,262 +0,0 @@
1
- // 测试db.js中的所有方法
2
- const { Sqlite } = require('./index');
3
- const path = require('path');
4
-
5
- async function testDbMethods() {
6
- let sql;
7
- try {
8
- console.log('=== 开始测试 mm_sqlite/db.js 中的方法 ===\n');
9
-
10
- // 初始化SQLite实例
11
- sql = new Sqlite({
12
- database: './db/test_db_methods.db'
13
- });
14
-
15
- await sql.open();
16
- console.log('✓ 数据库连接成功');
17
-
18
- // 获取数据库操作实例
19
- const db = sql.db();
20
- const test_table = 'test_db_methods';
21
- const backup_table = 'test_db_methods_backup';
22
-
23
- // 清理测试环境
24
- console.log('\n=== 1. 清理测试环境 ===');
25
- await db.dropTable(test_table);
26
- await db.dropTable(backup_table);
27
- console.log('✓ 测试环境清理完成');
28
-
29
- // 2. 测试表操作方法
30
- console.log('\n=== 2. 测试表操作方法 ===');
31
-
32
- // 测试addTable
33
- console.log('测试addTable()方法...');
34
- const createResult = await db.addTable(test_table, 'id', 'int', true, '测试表');
35
- console.log('✓ 表创建结果:', createResult);
36
-
37
- // 测试hasTable
38
- console.log('测试hasTable()方法...');
39
- const hasTableResult = await db.hasTable(test_table);
40
- console.log('✓ 表是否存在:', hasTableResult);
41
-
42
- // 测试tables
43
- console.log('测试tables()方法...');
44
- const tablesResult = await db.tables();
45
- console.log('✓ 表列表:', tablesResult);
46
-
47
- // 3. 测试字段操作方法
48
- console.log('\n=== 3. 测试字段操作方法 ===');
49
-
50
- // 设置表名
51
- db.table = test_table;
52
-
53
- // 测试addField
54
- console.log('测试addField()方法...');
55
- const addFieldResult1 = await db.addField('username', 'varchar', '', true, false, '用户名');
56
- console.log('✓ 添加username字段结果:', addFieldResult1);
57
-
58
- // 测试addField(添加email字段)
59
- console.log('测试addField()方法(添加email字段)...');
60
- const addFieldResult2 = await db.addField('email', 'varchar', '', true, false, '邮箱');
61
- console.log('✓ 添加email字段结果:', addFieldResult2);
62
-
63
- // 测试addField(添加age字段)
64
- console.log('测试addField()方法(添加age字段)...');
65
- const addFieldResult3 = await db.addField('age', 'int', 0, true, false, '年龄');
66
- console.log('✓ 添加age字段结果:', addFieldResult3);
67
-
68
- // 测试setField
69
- console.log('测试setField()方法...');
70
- const setFieldResult = await db.setField('email', 'varchar', '', true, false, '电子邮箱');
71
- console.log('✓ 修改email字段结果:', setFieldResult);
72
-
73
- // 测试addField(添加temp字段用于后续delField测试)
74
- console.log('测试addField()方法(添加temp字段)...');
75
- await db.addField('temp', 'int', 0, false, false, '临时字段');
76
- console.log('✓ 添加temp字段结果: 成功');
77
-
78
- // 测试fields
79
- console.log('测试fields()方法...');
80
- const fieldsResult = await db.fields();
81
- console.log('✓ 字段信息:', fieldsResult.map(f => f.name));
82
-
83
- // 测试hasField
84
- console.log('测试hasField()方法...');
85
- const hasFieldResult = await db.hasField(test_table, 'username');
86
- console.log('✓ username字段是否存在:', hasFieldResult);
87
-
88
- // 测试delField
89
- console.log('测试delField()方法...');
90
- const delFieldResult = await db.delField(test_table, 'temp');
91
- console.log('✓ 删除temp字段结果:', delFieldResult);
92
-
93
- // 测试renameField
94
- console.log('测试renameField()方法...');
95
- try {
96
- // 先检查当前字段
97
- const fieldsBefore = await db.fields();
98
- console.log(' - 重命名前字段:', fieldsBefore.map(f => f.name));
99
-
100
- const renameFieldResult = await db.renameField(test_table, 'age', 'user_age');
101
- console.log(' - 重命名age字段结果:', renameFieldResult);
102
-
103
- // 检查重命名后字段
104
- const fieldsAfter = await db.fields();
105
- console.log(' - 重命名后字段:', fieldsAfter.map(f => f.name));
106
-
107
- // 只有当user_age字段存在时,才尝试重命名回age字段
108
- const hasUserAgeField = fieldsAfter.some(f => f.name === 'user_age');
109
- if (hasUserAgeField) {
110
- // 重命名回age字段,保持后续测试一致
111
- await db.renameField(test_table, 'user_age', 'age');
112
- console.log(' - 重命名user_age字段回age结果: 成功');
113
-
114
- // 再次检查字段
115
- const fieldsFinal = await db.fields();
116
- console.log(' - 最终字段:', fieldsFinal.map(f => f.name));
117
- } else {
118
- console.warn(' - user_age字段不存在,跳过重命名回age字段');
119
- }
120
-
121
- console.log('✓ renameField方法测试完成');
122
- } catch (error) {
123
- console.warn('⚠️ renameField()方法测试失败:', error.message);
124
- console.log('⚠️ renameField()方法测试跳过');
125
- }
126
-
127
- // 4. 测试数据操作方法
128
- console.log('\n=== 4. 测试数据操作方法 ===');
129
-
130
- // 测试add(插入数据)
131
- console.log('测试add()方法...');
132
- const addResult = await db.add({
133
- username: 'test_user',
134
- email: 'test@example.com',
135
- age: 25
136
- });
137
- console.log('✓ 插入数据结果:', addResult);
138
-
139
- // 测试get(查询单条数据)
140
- console.log('测试get()方法...');
141
- const getResult = await db.get({ id: 1 });
142
- console.log('✓ 查询单条数据结果:', getResult[0]);
143
-
144
- // 测试get(查询多条数据)
145
- console.log('测试get()方法(查询多条数据)...');
146
- const listResult = await db.get();
147
- console.log('✓ 查询多条数据结果:', listResult.length);
148
-
149
- // 测试set(更新数据)
150
- console.log('测试set()方法...');
151
- const setResult = await db.set({ id: 1 }, { age: 26 });
152
- console.log('✓ 更新数据结果:', setResult);
153
-
154
- // 测试set(另一种查询条件更新方式)
155
- console.log('测试set()方法(使用where属性)...');
156
- db.where = { id: 1 };
157
- const setResult2 = await db.set(db.where, { age: 27 });
158
- console.log('✓ set方法(使用where属性)更新结果:', setResult2);
159
-
160
- // 测试del(删除数据)
161
- console.log('测试del()方法...');
162
- const delResult = await db.del({ id: 1 });
163
- console.log('✓ 删除数据结果:', delResult);
164
-
165
- // 5. 测试事务操作方法
166
- console.log('\n=== 5. 测试事务操作方法 ===');
167
-
168
- // 重新插入一条数据用于事务测试
169
- await db.add({
170
- username: 'transaction_test',
171
- email: 'transaction@example.com',
172
- age: 30
173
- });
174
-
175
- try {
176
- // 测试start(开始事务)
177
- console.log(' - 事务开始');
178
- await db.start();
179
-
180
- // 在事务中插入数据
181
- await db.add({
182
- username: 'transaction_user',
183
- email: 'user@example.com',
184
- age: 35
185
- });
186
- console.log(' - 事务中插入数据成功');
187
-
188
- // 测试commit(提交事务)
189
- await db.commit();
190
- console.log(' - 事务提交成功');
191
-
192
- // 验证事务提交结果
193
- const transactionResult = await db.get();
194
- console.log(' - 事务后数据总数:', transactionResult.length);
195
-
196
- } catch (error) {
197
- // 测试back(回滚事务)
198
- await db.back();
199
- console.log(' - 事务回滚');
200
- throw error;
201
- } finally {
202
- // 测试end(结束事务)
203
- db.end();
204
- }
205
- console.log('✓ 事务操作完成');
206
-
207
- // 6. 测试其他方法
208
- console.log('\n=== 6. 测试其他方法 ===');
209
-
210
- // 测试getCreateTable
211
- console.log('测试getCreateTable()方法...');
212
- const createTableResult = await db.getCreateTable(test_table);
213
- console.log('✓ 表创建语句:', createTableResult);
214
-
215
- // 测试backupTable
216
- console.log('测试backupTable()方法...');
217
- const backupResult = await db.backupTable(test_table, backup_table);
218
- console.log('✓ 表备份结果:', backupResult);
219
-
220
- // 测试hasTable(备份表)
221
- console.log('测试hasTable()方法(备份表)...');
222
- const hasBackupTableResult = await db.hasTable(backup_table);
223
- console.log('✓ 备份表是否存在:', hasBackupTableResult);
224
-
225
- // 测试emptyTable
226
- console.log('测试emptyTable()方法...');
227
- const emptyResult = await db.emptyTable(test_table);
228
- console.log('✓ 清空表结果:', emptyResult);
229
-
230
- // 7. 清理测试环境
231
- console.log('\n=== 7. 清理测试环境 ===');
232
- await db.dropTable(test_table);
233
- await db.dropTable(backup_table);
234
- console.log('✓ 测试环境清理完成');
235
-
236
- // 关闭数据库连接
237
- console.log('\n=== 8. 关闭数据库连接 ===');
238
- await sql.close();
239
- console.log('✓ 数据库连接关闭成功');
240
-
241
- console.log('\n' + '='.repeat(50));
242
- console.log('所有测试完成!db.js方法测试通过');
243
- console.log('='.repeat(50));
244
-
245
- } catch (error) {
246
- console.error('\n测试失败:', error.message);
247
- // 关闭数据库连接
248
- try {
249
- if (sql) await sql.close();
250
- } catch (closeError) {
251
- console.error('关闭数据库连接失败:', closeError.message);
252
- }
253
- process.exit(1);
254
- }
255
- }
256
-
257
- // 运行测试
258
- testDbMethods();
259
-
260
- setTimeout(() => {
261
- process.exit(0);
262
- }, 5000);