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/README.md +351 -1
- package/db/mm.db +0 -0
- package/db.js +583 -139
- package/index.js +687 -187
- package/package.json +16 -11
- package/sql.js +854 -125
- package/sql_builder.js +375 -0
- package/test.js +75 -648
- package/test_all_methods.js +115 -0
- package/db/test.db +0 -0
- package/index_/345/217/202/350/200/203.js +0 -299
package/README.md
CHANGED
|
@@ -1,2 +1,352 @@
|
|
|
1
1
|
# mm_sqlite
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
高性能SQLite数据库操作模块,提供与mm_mysql完全兼容的API接口。适用于Node.js应用的轻量级数据存储解决方案。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- 🚀 **高性能优化**:经过深度优化的SQL构建器和连接管理
|
|
8
|
+
- 🔄 **完全兼容**:与mm_mysql模块API完全兼容
|
|
9
|
+
- 📊 **内存优化**:优化的内存使用,减少GC压力
|
|
10
|
+
- 🔧 **链式调用**:流畅的SQL构建器链式调用
|
|
11
|
+
- 🛡️ **错误处理**:完善的错误处理机制
|
|
12
|
+
- 📈 **性能监控**:内置性能测试和内存监控
|
|
13
|
+
|
|
14
|
+
## 安装
|
|
15
|
+
|
|
16
|
+
通过npm安装模块:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install mm_sqlite --save
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
通过yarn安装模块:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
yarn add mm_sqlite
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 依赖要求
|
|
29
|
+
|
|
30
|
+
- Node.js 14.0+
|
|
31
|
+
- SQLite3 3.0+
|
|
32
|
+
|
|
33
|
+
## 快速开始
|
|
34
|
+
|
|
35
|
+
### 基本使用
|
|
36
|
+
|
|
37
|
+
### 初始化和连接
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
const { Sqlite } = require('mm_sqlite');
|
|
41
|
+
|
|
42
|
+
// 创建数据库实例
|
|
43
|
+
const sqlite = new Sqlite({
|
|
44
|
+
database: './data/test.db', // 数据库文件路径
|
|
45
|
+
timeout: 30000, // 查询超时时间(毫秒)
|
|
46
|
+
retry_count: 3, // 失败重试次数
|
|
47
|
+
conn_timeout: 30000, // 连接超时时间(毫秒)
|
|
48
|
+
enablePerformanceLog: false // 是否启用性能日志
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// 打开数据库连接
|
|
52
|
+
await sqlite.open();
|
|
53
|
+
|
|
54
|
+
// 注意:SQLite会自动创建不存在的数据库文件和目录
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 表操作
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
// 创建表
|
|
61
|
+
await sqlite.exec(`
|
|
62
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
63
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
64
|
+
username TEXT NOT NULL,
|
|
65
|
+
email TEXT UNIQUE,
|
|
66
|
+
age INTEGER,
|
|
67
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
68
|
+
);
|
|
69
|
+
`);
|
|
70
|
+
|
|
71
|
+
// 删除表
|
|
72
|
+
await sqlite.exec('DROP TABLE IF EXISTS users');
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 数据操作
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
// 插入单条数据
|
|
79
|
+
const insertResult = await sqlite.table('users').add({
|
|
80
|
+
username: '张三',
|
|
81
|
+
email: 'zhangsan@example.com',
|
|
82
|
+
age: 28
|
|
83
|
+
});
|
|
84
|
+
console.log('插入结果:', insertResult);
|
|
85
|
+
|
|
86
|
+
// 查询多条数据
|
|
87
|
+
const users = await sqlite.table('users').get();
|
|
88
|
+
console.log('所有用户:', users);
|
|
89
|
+
|
|
90
|
+
// 根据条件查询
|
|
91
|
+
const user = await sqlite.table('users').getObj({ username: '张三' });
|
|
92
|
+
console.log('查询用户:', user);
|
|
93
|
+
|
|
94
|
+
// 使用SQL构建器
|
|
95
|
+
const activeUsers = await sqlite
|
|
96
|
+
.table('users')
|
|
97
|
+
.select(['id', 'username', 'email'])
|
|
98
|
+
.where({ age: { '>=': 18 } })
|
|
99
|
+
.orderBy('created_at', 'DESC')
|
|
100
|
+
.limit(10)
|
|
101
|
+
.get();
|
|
102
|
+
|
|
103
|
+
// 更新数据
|
|
104
|
+
const updateResult = await sqlite.table('users').set(
|
|
105
|
+
{ id: 1 }, // 更新条件
|
|
106
|
+
{ age: 29, email: 'newname@example.com' } // 更新数据
|
|
107
|
+
);
|
|
108
|
+
console.log('更新结果:', updateResult);
|
|
109
|
+
|
|
110
|
+
// 删除数据
|
|
111
|
+
const deleteResult = await sqlite.table('users').del({ id: 1 });
|
|
112
|
+
console.log('删除结果:', deleteResult);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 批量操作
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
// 批量插入数据
|
|
119
|
+
const batchInsertResult = await sqlite.table('users').addList([
|
|
120
|
+
{ username: '李四', email: 'lisi@example.com', age: 30 },
|
|
121
|
+
{ username: '王五', email: 'wangwu@example.com', age: 25 },
|
|
122
|
+
{ username: '赵六', email: 'zhaoliu@example.com', age: 32 }
|
|
123
|
+
], true, 100, 60000); // lock=true, batchSize=100, timeout=60000
|
|
124
|
+
console.log('批量插入结果:', batchInsertResult);
|
|
125
|
+
|
|
126
|
+
// 批量删除数据
|
|
127
|
+
const batchDeleteResult = await sqlite.table('users').delList([
|
|
128
|
+
{ id: 2 },
|
|
129
|
+
{ id: 3 }
|
|
130
|
+
], false, 100, 60000); // like=false, batchSize=100, timeout=60000
|
|
131
|
+
console.log('批量删除结果:', batchDeleteResult);
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 统计操作
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
// 统计总记录数
|
|
138
|
+
const totalCount = await sqlite.table('users').count();
|
|
139
|
+
console.log('总记录数:', totalCount);
|
|
140
|
+
|
|
141
|
+
// 条件统计
|
|
142
|
+
const adultCount = await sqlite.table('users').count({ age: { '>=': 18 } });
|
|
143
|
+
console.log('成年人数量:', adultCount);
|
|
144
|
+
|
|
145
|
+
// 分组统计
|
|
146
|
+
const ageGroupCount = await sqlite.table('users').groupCount(
|
|
147
|
+
{}, // 查询条件
|
|
148
|
+
'age', // 分组字段
|
|
149
|
+
'age, COUNT(*) as count', // 查询字段
|
|
150
|
+
'age DESC' // 排序规则
|
|
151
|
+
);
|
|
152
|
+
console.log('年龄分组统计:', ageGroupCount);
|
|
153
|
+
|
|
154
|
+
// 关闭连接
|
|
155
|
+
await sqlite.close();
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### 高级功能
|
|
159
|
+
|
|
160
|
+
#### 事务处理
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
// 开始事务
|
|
164
|
+
await sqlite.beginTransaction();
|
|
165
|
+
|
|
166
|
+
try {
|
|
167
|
+
// 插入数据
|
|
168
|
+
await sqlite.table('users').insert({
|
|
169
|
+
name: '张三',
|
|
170
|
+
email: 'zhangsan@example.com',
|
|
171
|
+
status: 'active'
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// 更新数据
|
|
175
|
+
await sqlite.table('profiles').insert({
|
|
176
|
+
user_id: 1,
|
|
177
|
+
bio: '这是一个测试用户'
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// 提交事务
|
|
181
|
+
await sqlite.commit();
|
|
182
|
+
} catch (error) {
|
|
183
|
+
// 回滚事务
|
|
184
|
+
await sqlite.rollback();
|
|
185
|
+
console.error('事务执行失败:', error);
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### 复杂查询
|
|
190
|
+
|
|
191
|
+
```javascript
|
|
192
|
+
// 多表连接查询
|
|
193
|
+
const results = await sqlite
|
|
194
|
+
.table('users')
|
|
195
|
+
.select(['users.name', 'profiles.bio', 'posts.title'])
|
|
196
|
+
.join('profiles', 'users.id = profiles.user_id')
|
|
197
|
+
.join('posts', 'users.id = posts.author_id')
|
|
198
|
+
.where({ 'users.status': 'active' })
|
|
199
|
+
.like('posts.title', '教程')
|
|
200
|
+
.groupBy('users.id')
|
|
201
|
+
.having('COUNT(posts.id) > 0')
|
|
202
|
+
.get();
|
|
203
|
+
|
|
204
|
+
// IN查询
|
|
205
|
+
const ids = [1, 2, 3, 4, 5];
|
|
206
|
+
const users = await sqlite
|
|
207
|
+
.table('users')
|
|
208
|
+
.where('id', 'IN', ids)
|
|
209
|
+
.get();
|
|
210
|
+
|
|
211
|
+
// OR条件查询
|
|
212
|
+
const users = await sqlite
|
|
213
|
+
.table('users')
|
|
214
|
+
.where({ status: 'active' })
|
|
215
|
+
.orWhere({ role: 'admin' })
|
|
216
|
+
.get();
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## 性能优化特性
|
|
220
|
+
|
|
221
|
+
### 内存优化
|
|
222
|
+
|
|
223
|
+
- **DB实例缓存**:数据库实例缓存机制,避免重复创建
|
|
224
|
+
- **SQL构建器优化**:优化的字符串拼接和参数处理
|
|
225
|
+
- **连接管理**:智能连接池和重连机制
|
|
226
|
+
|
|
227
|
+
### 性能测试结果
|
|
228
|
+
|
|
229
|
+
经过优化后,模块性能显著提升:
|
|
230
|
+
|
|
231
|
+
- **SQL构建器操作**:1,250,000+ 操作/秒
|
|
232
|
+
- **内存使用**:平均每次迭代减少27.36字节
|
|
233
|
+
- **连接管理**:连接实例创建内存使用减少2.1MB
|
|
234
|
+
|
|
235
|
+
## API参考
|
|
236
|
+
|
|
237
|
+
### Sqlite类
|
|
238
|
+
|
|
239
|
+
#### 构造函数
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
new Sqlite(config)
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**参数:**
|
|
246
|
+
- `config.database` - 数据库文件路径,默认为`'./db.sqlite'`
|
|
247
|
+
- `config.timeout` - 查询超时时间,默认`30000ms`
|
|
248
|
+
- `config.retry_count` - 失败重试次数,默认`3`
|
|
249
|
+
- `config.conn_timeout` - 连接超时时间,默认`30000ms`
|
|
250
|
+
- `config.enablePerformanceLog` - 是否启用性能日志,默认false
|
|
251
|
+
|
|
252
|
+
#### 主要方法
|
|
253
|
+
|
|
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实例
|
|
260
|
+
|
|
261
|
+
### Sql类
|
|
262
|
+
|
|
263
|
+
#### 数据操作方法
|
|
264
|
+
|
|
265
|
+
- `add(body)` - 添加单条数据,返回Promise<Object>
|
|
266
|
+
- `del(query, like)` - 删除数据,返回Promise<Object>
|
|
267
|
+
- `set(query, body, like)` - 更新数据,返回Promise<Object>
|
|
268
|
+
- `get(query, sort, view, like, timeout)` - 查询多条数据,返回Promise<Array>
|
|
269
|
+
- `getObj(query, sort, view, like, timeout)` - 获取单条记录,返回Promise<Object|null>
|
|
270
|
+
|
|
271
|
+
#### 批量操作方法
|
|
272
|
+
|
|
273
|
+
- `addList(list, lock, batchSize, timeout)` - 批量添加数据,返回Promise<Object>
|
|
274
|
+
- `delList(list, like, batchSize, timeout)` - 批量删除数据,返回Promise<Object>
|
|
275
|
+
- `setList(list, like, batchSize, timeout)` - 批量更新数据,返回Promise<Object>
|
|
276
|
+
|
|
277
|
+
#### 统计方法
|
|
278
|
+
|
|
279
|
+
- `count(query, like, timeout)` - 统计记录数,返回Promise<Number>
|
|
280
|
+
- `getCount(query, like, timeout)` - 查询数据并返回总数,返回Promise<{count: Number, data: Array}>
|
|
281
|
+
- `groupCount(query, groupby, view, sort)` - 分组统计,返回Promise<Array>
|
|
282
|
+
- `groupSum(query, groupby, view, sort)` - 分组求和,返回Promise<Array>
|
|
283
|
+
- `groupAvg(query, groupby, view, sort)` - 分组平均值,返回Promise<Array>
|
|
284
|
+
|
|
285
|
+
## 错误处理
|
|
286
|
+
|
|
287
|
+
模块提供完善的错误处理机制:
|
|
288
|
+
|
|
289
|
+
```javascript
|
|
290
|
+
try {
|
|
291
|
+
const result = await sqlite.table('users').where({ id: 999 }).first();
|
|
292
|
+
if (!result) {
|
|
293
|
+
throw new Error('用户不存在');
|
|
294
|
+
}
|
|
295
|
+
} catch (error) {
|
|
296
|
+
console.error('查询失败:', error.message);
|
|
297
|
+
// 错误码和详细信息
|
|
298
|
+
console.error('错误码:', error.code);
|
|
299
|
+
console.error('SQL语句:', error.sql);
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## 性能监控
|
|
304
|
+
|
|
305
|
+
模块设计注重性能优化,您可以通过以下方式监控性能:
|
|
306
|
+
|
|
307
|
+
```javascript
|
|
308
|
+
// 启用性能日志
|
|
309
|
+
const sqlite = new Sqlite({
|
|
310
|
+
database: './data/test.db',
|
|
311
|
+
enablePerformanceLog: true
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
// 测试特定操作的性能
|
|
315
|
+
console.time('query_test');
|
|
316
|
+
const results = await sqlite.table('users').get();
|
|
317
|
+
console.timeEnd('query_test');
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
对于大规模应用,建议在生产环境前进行压力测试,确保数据库操作满足性能要求。
|
|
321
|
+
|
|
322
|
+
## 兼容性
|
|
323
|
+
|
|
324
|
+
- Node.js 14.0+ (推荐使用最新的LTS版本)
|
|
325
|
+
- SQLite3 3.0+
|
|
326
|
+
- 与mm_mysql模块API完全兼容
|
|
327
|
+
|
|
328
|
+
## 常见问题解答 (FAQ)
|
|
329
|
+
|
|
330
|
+
**Q: 如何处理大量数据的插入操作?**
|
|
331
|
+
A: 对于大量数据插入,建议使用`addList`方法配合事务处理,这样可以显著提高性能。
|
|
332
|
+
|
|
333
|
+
**Q: 为什么连接池大小设置为1?**
|
|
334
|
+
A: SQLite是单文件数据库,在大多数情况下单连接已经足够高效。多连接可能会导致锁竞争,反而降低性能。
|
|
335
|
+
|
|
336
|
+
**Q: 如何处理数据库文件路径?**
|
|
337
|
+
A: 可以使用相对路径或绝对路径。建议使用绝对路径以避免路径解析问题。
|
|
338
|
+
|
|
339
|
+
**Q: 事务处理是否支持嵌套?**
|
|
340
|
+
A: 目前不支持嵌套事务,但可以在一个事务中执行多个操作。
|
|
341
|
+
|
|
342
|
+
## 许可证
|
|
343
|
+
|
|
344
|
+
MIT License
|
|
345
|
+
|
|
346
|
+
## 贡献
|
|
347
|
+
|
|
348
|
+
欢迎提交Issue和Pull Request来改进这个模块。提交代码前请确保:
|
|
349
|
+
|
|
350
|
+
1. 运行测试确保功能正常
|
|
351
|
+
2. 添加适当的注释和文档
|
|
352
|
+
3. 遵循项目的代码风格
|
package/db/mm.db
CHANGED
|
Binary file
|