mm_sqlite 1.1.3 → 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,7 +11,7 @@ class Sqlite extends BaseService {
12
11
  * 默认配置
13
12
  */
14
13
  static default_config = {
15
- dir: "/db/".fullname(),
14
+ dir: "./db/".fullname(),
16
15
  user: "root",
17
16
  password: "",
18
17
  database: "mm",
@@ -136,19 +135,16 @@ Sqlite.prototype.open = async function (timeout) {
136
135
  Sqlite.prototype._openInternal = function () {
137
136
  return new Promise((resolve, reject) => {
138
137
  try {
139
- const fs = require('fs');
140
- const path = require('path');
141
138
 
142
139
  // 确保数据库目录存在
143
- const db_path = this._getDatabasePath();
144
- const dir = path.dirname(db_path);
140
+ const file = this._getDatabasePath();
145
141
 
146
- if (!fs.existsSync(dir)) {
147
- fs.mkdirSync(dir, { recursive: true });
142
+ if (!file.hasDir()) {
143
+ file.addDir();
148
144
  }
149
145
 
150
146
  // 创建数据库连接
151
- this._db = new sqlite3.Database(db_path);
147
+ this._db = new sqlite3.Database(file);
152
148
  this._open = true;
153
149
  this._conn_retry_count = 0;
154
150
 
@@ -158,7 +154,7 @@ Sqlite.prototype._openInternal = function () {
158
154
  this._handleConnectionError(err);
159
155
  });
160
156
 
161
- $.log.debug(`SQLite数据库已打开: ${db_path}`);
157
+ $.log.debug(`SQLite数据库已打开: ${file}`);
162
158
  resolve();
163
159
  } catch (error) {
164
160
  reject(error);
@@ -173,8 +169,11 @@ Sqlite.prototype._openInternal = function () {
173
169
  */
174
170
  Sqlite.prototype._getDatabasePath = function () {
175
171
  const db_name = this.config.database || 'mm';
176
- const db_dir = this.config.dir || '/db/';
177
- 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);
178
177
  };
179
178
 
180
179
  /**
@@ -674,6 +673,23 @@ Sqlite.prototype.transaction = async function (callback) {
674
673
  }
675
674
  };
676
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
+
677
693
  /**
678
694
  * 确保连接池对象存在
679
695
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_sqlite",
3
- "version": "1.1.3",
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);