jj.js 0.18.0 → 0.19.0
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/CHANGELOG.md +5 -0
- package/lib/app.js +11 -8
- package/lib/config.js +7 -2
- package/lib/db/mysql.js +290 -0
- package/lib/db/sql.js +106 -0
- package/lib/db/sqlite.js +284 -0
- package/lib/db.js +64 -252
- package/lib/request.js +3 -0
- package/package.json +5 -2
- package/types.js +4 -1
package/CHANGELOG.md
CHANGED
package/lib/app.js
CHANGED
|
@@ -12,11 +12,17 @@ const pjson = require('../package.json');
|
|
|
12
12
|
*/
|
|
13
13
|
class App extends Koa
|
|
14
14
|
{
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
constructor(beforeUse, options) {
|
|
16
|
+
if(typeof beforeUse === 'function') {
|
|
17
|
+
super(options);
|
|
18
|
+
this.use(beforeUse);
|
|
19
|
+
} else {
|
|
20
|
+
super(beforeUse);
|
|
21
|
+
}
|
|
22
|
+
this._init();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
_init() {
|
|
20
26
|
// storage
|
|
21
27
|
this.use(async (ctx, next) => {
|
|
22
28
|
await storage.run({}, async() => {
|
|
@@ -63,9 +69,6 @@ class App extends Koa
|
|
|
63
69
|
const jsconfigFile = path.join(cfg_app.base_dir, 'jsconfig.json');
|
|
64
70
|
isFileSync(jsconfigFile) && require('./types')();
|
|
65
71
|
}
|
|
66
|
-
|
|
67
|
-
// server
|
|
68
|
-
return super.listen(...args);
|
|
69
72
|
}
|
|
70
73
|
}
|
|
71
74
|
|
package/lib/config.js
CHANGED
|
@@ -34,9 +34,14 @@ const db = {
|
|
|
34
34
|
user : 'root', // 数据库用户名
|
|
35
35
|
password : '', // 数据库密码
|
|
36
36
|
port : '', // 数据库连接端口
|
|
37
|
-
charset : '
|
|
37
|
+
charset : 'utf8mb4', // 数据库编码默认采用utf8mb4
|
|
38
38
|
prefix : 'jj_' // 数据库表前缀
|
|
39
|
-
}
|
|
39
|
+
},
|
|
40
|
+
sqlite: {
|
|
41
|
+
type : 'sqlite', // 数据库类型
|
|
42
|
+
database : ':memory:', // 数据库文件绝对地址,支持:memory:内存数据库
|
|
43
|
+
prefix : 'jj_' // 数据库表前缀
|
|
44
|
+
},
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
const log = {
|
package/lib/db/mysql.js
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
const Sql = require('./sql');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {import('../../types').Pool} Pool
|
|
5
|
+
* @typedef {import('../../types').PoolConfig} PoolConfig
|
|
6
|
+
* @typedef {import('../../types').PoolConnection} PoolConnection
|
|
7
|
+
* @typedef {import('../../types').FieldInfo} FieldInfo
|
|
8
|
+
* @typedef {Map<any, Pool>} PoolMap
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
//连接池
|
|
12
|
+
/**
|
|
13
|
+
* @type {PoolMap}
|
|
14
|
+
*/
|
|
15
|
+
const pool = new Map();
|
|
16
|
+
//事务连接
|
|
17
|
+
const trans = new Map();
|
|
18
|
+
//事务嵌套
|
|
19
|
+
const nest = new Map();
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @extends Sql
|
|
23
|
+
*/
|
|
24
|
+
class Mysql extends Sql
|
|
25
|
+
{
|
|
26
|
+
/**
|
|
27
|
+
* 连接数据库连接池
|
|
28
|
+
* @public
|
|
29
|
+
* @param {PoolConfig} config - 数据库配置标识或连接参数
|
|
30
|
+
* @returns {Promise<this>}
|
|
31
|
+
}
|
|
32
|
+
*/
|
|
33
|
+
async connect(config={}) {
|
|
34
|
+
this._config = config;
|
|
35
|
+
|
|
36
|
+
if(!pool.has(this._config)) {
|
|
37
|
+
const cur_pool = require('mysql').createPool(this._config);
|
|
38
|
+
pool.set(this._config, cur_pool);
|
|
39
|
+
this.$logger.sql(`MYSQL连接池创建成功:{all: ${pool.size}}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 关闭数据库连接池
|
|
47
|
+
* @public
|
|
48
|
+
* @returns {Promise}
|
|
49
|
+
*/
|
|
50
|
+
async close() {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
if(pool.has(this._config)) {
|
|
53
|
+
pool.get(this._config).end(err => {
|
|
54
|
+
if(err) {
|
|
55
|
+
const message = 'MYSQL连接池销毁失败:' + err.message;
|
|
56
|
+
this.$logger.sql(message);
|
|
57
|
+
this.$logger.error(message);
|
|
58
|
+
reject(new Error('DbError: ' + message));
|
|
59
|
+
} else {
|
|
60
|
+
pool.delete(this._config);
|
|
61
|
+
this.$logger.sql(`MYSQL连接池销毁成功:{poolTotal: ${pool.size}}`);
|
|
62
|
+
resolve(this);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
} else {
|
|
66
|
+
resolve(this);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 释放数据库连接
|
|
73
|
+
* @public
|
|
74
|
+
* @param {PoolConnection} conn - 数据库连接
|
|
75
|
+
*/
|
|
76
|
+
release(conn) {
|
|
77
|
+
try {
|
|
78
|
+
conn.release();
|
|
79
|
+
this.$logger.sql('释放数据库连接!');
|
|
80
|
+
} catch(e) {
|
|
81
|
+
const message = '释放数据库出错:' + e.message;
|
|
82
|
+
this.$logger.sql(message);
|
|
83
|
+
this.$logger.error(message);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 获取数据库连接
|
|
89
|
+
* @private
|
|
90
|
+
* @param {Pool} p
|
|
91
|
+
* @returns {Promise<PoolConnection>}
|
|
92
|
+
*/
|
|
93
|
+
async _creatConnect(p) {
|
|
94
|
+
return new Promise((resolve, reject) => {
|
|
95
|
+
p.getConnection((err, connection) => {
|
|
96
|
+
if(err) {
|
|
97
|
+
const message = '获取数据库连接失败:' + err.message;
|
|
98
|
+
this.$logger.sql(message);
|
|
99
|
+
this.$logger.error(message);
|
|
100
|
+
reject(new Error('DbError: ' + message));
|
|
101
|
+
} else {
|
|
102
|
+
this.$logger.sql(`获取数据库连接:{limit: ${p.config.connectionLimit}, all: ${p._allConnections.length}, acquiring: ${p._acquiringConnections.length}, free: ${p._freeConnections.length}, queue: ${p._connectionQueue.length}}`);
|
|
103
|
+
resolve(connection);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 获取数据库连接
|
|
111
|
+
* @private
|
|
112
|
+
* @returns {Promise<PoolConnection>}
|
|
113
|
+
*/
|
|
114
|
+
async _getConnect() {
|
|
115
|
+
return trans.get(this.ctx) || await this._creatConnect(pool.get(this._config));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* 开启事务
|
|
120
|
+
* @public
|
|
121
|
+
* @param {function} fun
|
|
122
|
+
* @returns {Promise<string>}
|
|
123
|
+
*/
|
|
124
|
+
async startTrans(fun) {
|
|
125
|
+
const conn = await this._getConnect();
|
|
126
|
+
trans.set(this.ctx, conn);
|
|
127
|
+
let trans_nest = nest.get(conn) || 0;
|
|
128
|
+
nest.set(conn, ++trans_nest);
|
|
129
|
+
if(trans_nest > 1) {
|
|
130
|
+
const message = `开启事务成功:{nest:${trans_nest}}`;
|
|
131
|
+
this.$logger.sql(message);
|
|
132
|
+
if(typeof fun === 'function') {
|
|
133
|
+
try {
|
|
134
|
+
await fun();
|
|
135
|
+
await this.commit();
|
|
136
|
+
} catch(e) {
|
|
137
|
+
await this.rollback();
|
|
138
|
+
throw e;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return message;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return new Promise((resolve, reject) => {
|
|
145
|
+
conn.beginTransaction(async err => {
|
|
146
|
+
if(err) {
|
|
147
|
+
const message = '开启事务失败:' + err.message;
|
|
148
|
+
this.$logger.sql(message);
|
|
149
|
+
this.$logger.error(message);
|
|
150
|
+
reject(new Error('DbError: ' + message));
|
|
151
|
+
} else {
|
|
152
|
+
const message = '开启事务成功!';
|
|
153
|
+
this.$logger.sql(message);
|
|
154
|
+
if(typeof fun === 'function') {
|
|
155
|
+
try {
|
|
156
|
+
await fun();
|
|
157
|
+
await this.commit();
|
|
158
|
+
resolve('事务执行成功!');
|
|
159
|
+
} catch(e) {
|
|
160
|
+
await this.rollback();
|
|
161
|
+
reject(e);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
resolve(message);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 事务回滚
|
|
172
|
+
* @public
|
|
173
|
+
* @returns {Promise<string>}
|
|
174
|
+
*/
|
|
175
|
+
async rollback() {
|
|
176
|
+
const conn = await this._getConnect();
|
|
177
|
+
const trans_nest = nest.get(conn) || 0;
|
|
178
|
+
if(trans_nest > 1) {
|
|
179
|
+
nest.set(conn, trans_nest - 1);
|
|
180
|
+
const message = `事务回滚成功:{nest:${trans_nest}}`;
|
|
181
|
+
this.$logger.sql(message);
|
|
182
|
+
return message;
|
|
183
|
+
} else {
|
|
184
|
+
nest.delete(conn);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return new Promise((resolve, reject) => {
|
|
188
|
+
conn.rollback(err => {
|
|
189
|
+
if(err) {
|
|
190
|
+
reject(new Error('DbError: ' + err.message));
|
|
191
|
+
} else {
|
|
192
|
+
trans.delete(this.ctx);
|
|
193
|
+
const message = '事务回滚成功!';
|
|
194
|
+
this.$logger.sql(message);
|
|
195
|
+
this.release(conn);
|
|
196
|
+
resolve(message);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* 提交事务
|
|
204
|
+
* @public
|
|
205
|
+
* @returns {Promise<string>}
|
|
206
|
+
*/
|
|
207
|
+
async commit() {
|
|
208
|
+
const conn = await this._getConnect();
|
|
209
|
+
const trans_nest = nest.get(conn) || 0;
|
|
210
|
+
if(trans_nest > 1) {
|
|
211
|
+
nest.set(conn, trans_nest - 1);
|
|
212
|
+
const message = `事务提交成功:{nest:${trans_nest}}`;
|
|
213
|
+
this.$logger.sql(message);
|
|
214
|
+
return message;
|
|
215
|
+
} else {
|
|
216
|
+
nest.delete(conn);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return new Promise((resolve, reject) => {
|
|
220
|
+
conn.commit(err => {
|
|
221
|
+
if(err) {
|
|
222
|
+
const message = '事务提交失败:' + err.message;
|
|
223
|
+
this.$logger.sql(message);
|
|
224
|
+
this.$logger.error(message);
|
|
225
|
+
this.rollback();
|
|
226
|
+
reject(new Error('DbError: ' + message));
|
|
227
|
+
} else {
|
|
228
|
+
trans.delete(this.ctx);
|
|
229
|
+
const message = '事务提交成功!';
|
|
230
|
+
this.$logger.sql(message);
|
|
231
|
+
this.release(conn);
|
|
232
|
+
resolve(message);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* 执行sql查询
|
|
240
|
+
* @public
|
|
241
|
+
* @param {string} sql - sql语句或参数
|
|
242
|
+
* @param {*} params - sql参数
|
|
243
|
+
* @returns {Promise}
|
|
244
|
+
*/
|
|
245
|
+
async query(sql, params) {
|
|
246
|
+
params || (params = []);
|
|
247
|
+
const conn = await this._getConnect();
|
|
248
|
+
|
|
249
|
+
return new Promise((resolve, reject) => {
|
|
250
|
+
conn.query(sql, params, (err, data) => {
|
|
251
|
+
if(err) {
|
|
252
|
+
const message = '数据操作失败,' + err.message + "\nSQL:" + this.format(sql, params);
|
|
253
|
+
this.$logger.sql(message);
|
|
254
|
+
this.$logger.error(message);
|
|
255
|
+
reject(new Error('DbError: ' + message));
|
|
256
|
+
} else {
|
|
257
|
+
this.$logger.sql('数据操作成功,SQL:' + this.format(sql, params));
|
|
258
|
+
resolve(data);
|
|
259
|
+
}
|
|
260
|
+
if(!trans.has(this.ctx)) {
|
|
261
|
+
this.release(conn);
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* 序列化sql语句
|
|
269
|
+
* @public
|
|
270
|
+
* @param {string} sql - sql语句或参数
|
|
271
|
+
* @param {*} params - sql参数
|
|
272
|
+
* @returns {string}
|
|
273
|
+
*/
|
|
274
|
+
format(sql, params) {
|
|
275
|
+
params || (params = []);
|
|
276
|
+
return require('mysql').format(sql, params);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* 获取数据表信息
|
|
281
|
+
* @public
|
|
282
|
+
* @param {string} tableName - 表名字
|
|
283
|
+
* @returns {Promise<FieldInfo[]>}
|
|
284
|
+
*/
|
|
285
|
+
async tableInfo(tableName) {
|
|
286
|
+
return await this.query(`show columns from ?`, [tableName]);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
module.exports = Mysql;
|
package/lib/db/sql.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import('../../types').Logger} Logger
|
|
3
|
+
* @typedef {import('../../types').FieldInfo} FieldInfo
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class Sql
|
|
7
|
+
{
|
|
8
|
+
/**
|
|
9
|
+
* @public
|
|
10
|
+
* @param {object} ctx
|
|
11
|
+
* @param {Logger} logger
|
|
12
|
+
*/
|
|
13
|
+
constructor(ctx, logger) {
|
|
14
|
+
this.ctx = ctx;
|
|
15
|
+
this.$logger = logger;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 连接数据库
|
|
20
|
+
* @public
|
|
21
|
+
* @param {object} config - 数据库连接参数
|
|
22
|
+
* @returns {Promise<this>}
|
|
23
|
+
*/
|
|
24
|
+
async connect(config={}) {
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 关闭数据库
|
|
30
|
+
* @public
|
|
31
|
+
* @returns {Promise<this>}
|
|
32
|
+
*/
|
|
33
|
+
async close() {
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 释放数据库连接
|
|
39
|
+
* @public
|
|
40
|
+
* @param {object} conn - 数据库连接
|
|
41
|
+
*/
|
|
42
|
+
release(conn) {
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 开启事务
|
|
47
|
+
* @public
|
|
48
|
+
* @param {function} [fun]
|
|
49
|
+
* @returns {Promise<string>}
|
|
50
|
+
*/
|
|
51
|
+
async startTrans(fun) {
|
|
52
|
+
return '开启事务成功';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 事务回滚
|
|
57
|
+
* @public
|
|
58
|
+
* @returns {Promise<string>}
|
|
59
|
+
*/
|
|
60
|
+
async rollback() {
|
|
61
|
+
return '事务回滚成功';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 提交事务
|
|
66
|
+
* @public
|
|
67
|
+
* @returns {Promise<string>}
|
|
68
|
+
*/
|
|
69
|
+
async commit() {
|
|
70
|
+
return '事务提交成功';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 执行sql查询
|
|
75
|
+
* @public
|
|
76
|
+
* @param {string} sql - sql语句或参数
|
|
77
|
+
* @param {*} params - sql参数
|
|
78
|
+
* @returns {Promise}
|
|
79
|
+
*/
|
|
80
|
+
async query(sql, params) {
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 序列化sql语句
|
|
85
|
+
* @public
|
|
86
|
+
* @param {string} sql - sql语句或参数
|
|
87
|
+
* @param {*} params - sql参数
|
|
88
|
+
* @returns {string}
|
|
89
|
+
*/
|
|
90
|
+
format(sql, params) {
|
|
91
|
+
params || (params = []);
|
|
92
|
+
return `${sql} ${params.map(item => item.join('=')).join(', ')}`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 获取数据表信息
|
|
97
|
+
* @public
|
|
98
|
+
* @param {string} tableName - 表名字
|
|
99
|
+
* @returns {Promise<FieldInfo[]>}
|
|
100
|
+
*/
|
|
101
|
+
async tableInfo(tableName) {
|
|
102
|
+
return await this.query(`show columns from ?`, [tableName]);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = Sql;
|
package/lib/db/sqlite.js
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
const {app: cfg_app} = require('../config');
|
|
2
|
+
const Sql = require('./sql');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import('sqlite3').Database} Database
|
|
6
|
+
* @typedef {import('../../types').FieldInfo} FieldInfo
|
|
7
|
+
* @typedef {Map<any, Database>} ConnectionMap
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
//数据库连接
|
|
11
|
+
/**
|
|
12
|
+
* @type {ConnectionMap}
|
|
13
|
+
*/
|
|
14
|
+
const connections = new Map();
|
|
15
|
+
//事务连接
|
|
16
|
+
const trans = new Map();
|
|
17
|
+
//事务嵌套
|
|
18
|
+
const nest = new Map();
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @extends Sql
|
|
22
|
+
*/
|
|
23
|
+
class Sqlite extends Sql
|
|
24
|
+
{
|
|
25
|
+
/**
|
|
26
|
+
* 连接数据库
|
|
27
|
+
* @public
|
|
28
|
+
* @param {object} config - 数据库配置标识或连接参数
|
|
29
|
+
* @returns {Promise<this>}
|
|
30
|
+
*/
|
|
31
|
+
async connect(config={}) {
|
|
32
|
+
this._config = config;
|
|
33
|
+
|
|
34
|
+
let connection = connections.get(this._config);
|
|
35
|
+
if(!connection) {
|
|
36
|
+
const sqlite3 = cfg_app.app_debug ? require('sqlite3').verbose() : require('sqlite3');
|
|
37
|
+
connection = new sqlite3.Database(this._config.database);
|
|
38
|
+
connections.set(this._config, connection);
|
|
39
|
+
this.$logger.sql(`SQLITE数据库连接创建成功:{all: ${connections.size}}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 关闭数据库连接
|
|
47
|
+
* @public
|
|
48
|
+
* @returns {Promise}
|
|
49
|
+
*/
|
|
50
|
+
async close() {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
if(connections.has(this._config)) {
|
|
53
|
+
const connection = connections.get(this._config);
|
|
54
|
+
connection.close(err => {
|
|
55
|
+
if(err) {
|
|
56
|
+
const message = 'SQLITE数据库连接关闭失败:' + err.message;
|
|
57
|
+
this.$logger.sql(message);
|
|
58
|
+
this.$logger.error(message);
|
|
59
|
+
reject(new Error('DbError: ' + message));
|
|
60
|
+
} else {
|
|
61
|
+
connections.delete(this._config);
|
|
62
|
+
this.$logger.sql(`SQLITE数据库连接关闭成功:{connectionTotal: ${connections.size}}`);
|
|
63
|
+
resolve(this);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
} else {
|
|
67
|
+
resolve(this);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 获取数据库连接
|
|
74
|
+
* @private
|
|
75
|
+
* @returns {Promise<Database>}
|
|
76
|
+
*/
|
|
77
|
+
async _getConnect() {
|
|
78
|
+
return trans.get(this.ctx) || connections.get(this._config);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* 开启事务
|
|
83
|
+
* @public
|
|
84
|
+
* @param {function} fun
|
|
85
|
+
* @returns {Promise<string>}
|
|
86
|
+
*/
|
|
87
|
+
async startTrans(fun) {
|
|
88
|
+
const conn = await this._getConnect();
|
|
89
|
+
trans.set(this.ctx, conn);
|
|
90
|
+
let trans_nest = nest.get(conn) || 0;
|
|
91
|
+
nest.set(conn, ++trans_nest);
|
|
92
|
+
if(trans_nest > 1) {
|
|
93
|
+
const message = `开启事务成功:{nest:${trans_nest}}`;
|
|
94
|
+
this.$logger.sql(message);
|
|
95
|
+
if(typeof fun === 'function') {
|
|
96
|
+
try {
|
|
97
|
+
await fun();
|
|
98
|
+
await this.commit();
|
|
99
|
+
} catch(e) {
|
|
100
|
+
await this.rollback();
|
|
101
|
+
throw e;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return message;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return new Promise((resolve, reject) => {
|
|
108
|
+
conn.run('BEGIN TRANSACTION;', async err => {
|
|
109
|
+
if(err) {
|
|
110
|
+
const message = '开启事务失败:' + err.message;
|
|
111
|
+
this.$logger.sql(message);
|
|
112
|
+
this.$logger.error(message);
|
|
113
|
+
reject(new Error('DbError: ' + message));
|
|
114
|
+
} else {
|
|
115
|
+
const message = '开启事务成功!';
|
|
116
|
+
this.$logger.sql(message);
|
|
117
|
+
if(typeof fun === 'function') {
|
|
118
|
+
try {
|
|
119
|
+
await fun();
|
|
120
|
+
await this.commit();
|
|
121
|
+
resolve('事务执行成功!');
|
|
122
|
+
} catch(e) {
|
|
123
|
+
await this.rollback();
|
|
124
|
+
reject(e);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
resolve(message);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* 事务回滚
|
|
135
|
+
* @public
|
|
136
|
+
* @returns {Promise<string>}
|
|
137
|
+
*/
|
|
138
|
+
async rollback() {
|
|
139
|
+
const conn = await this._getConnect();
|
|
140
|
+
const trans_nest = nest.get(conn) || 0;
|
|
141
|
+
if(trans_nest > 1) {
|
|
142
|
+
nest.set(conn, trans_nest - 1);
|
|
143
|
+
const message = `事务回滚成功:{nest:${trans_nest}}`;
|
|
144
|
+
this.$logger.sql(message);
|
|
145
|
+
return message;
|
|
146
|
+
} else {
|
|
147
|
+
nest.delete(conn);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return new Promise((resolve, reject) => {
|
|
151
|
+
conn.run('ROLLBACK;', err => {
|
|
152
|
+
if(err) {
|
|
153
|
+
reject(new Error('DbError: ' + err.message));
|
|
154
|
+
} else {
|
|
155
|
+
trans.delete(this.ctx);
|
|
156
|
+
const message = '事务回滚成功!';
|
|
157
|
+
this.$logger.sql(message);
|
|
158
|
+
resolve(message);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* 提交事务
|
|
166
|
+
* @public
|
|
167
|
+
* @returns {Promise<string>}
|
|
168
|
+
*/
|
|
169
|
+
async commit() {
|
|
170
|
+
const conn = await this._getConnect();
|
|
171
|
+
const trans_nest = nest.get(conn) || 0;
|
|
172
|
+
if(trans_nest > 1) {
|
|
173
|
+
nest.set(conn, trans_nest - 1);
|
|
174
|
+
const message = `事务提交成功:{nest:${trans_nest}}`;
|
|
175
|
+
this.$logger.sql(message);
|
|
176
|
+
return message;
|
|
177
|
+
} else {
|
|
178
|
+
nest.delete(conn);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return new Promise((resolve, reject) => {
|
|
182
|
+
conn.run('COMMIT;', err => {
|
|
183
|
+
if(err) {
|
|
184
|
+
const message = '事务提交失败:' + err.message;
|
|
185
|
+
this.$logger.sql(message);
|
|
186
|
+
this.$logger.error(message);
|
|
187
|
+
this.rollback();
|
|
188
|
+
reject(new Error('DbError: ' + message));
|
|
189
|
+
} else {
|
|
190
|
+
trans.delete(this.ctx);
|
|
191
|
+
const message = '事务提交成功!';
|
|
192
|
+
this.$logger.sql(message);
|
|
193
|
+
resolve(message);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 执行sql查询
|
|
201
|
+
* @public
|
|
202
|
+
* @param {string} sql - sql语句或参数
|
|
203
|
+
* @param {*} params - sql参数
|
|
204
|
+
* @returns {Promise}
|
|
205
|
+
*/
|
|
206
|
+
async query(sql, params) {
|
|
207
|
+
params || (params = []);
|
|
208
|
+
const conn = await this._getConnect();
|
|
209
|
+
|
|
210
|
+
return new Promise((resolve, reject) => {
|
|
211
|
+
// 判断是SELECT查询还是其他操作
|
|
212
|
+
const isSelect = /^\s*select /i.test(sql);
|
|
213
|
+
const isTableInfo = /^\s*PRAGMA table_info/i.test(sql);
|
|
214
|
+
|
|
215
|
+
const that = this;
|
|
216
|
+
conn[isSelect || isTableInfo ? 'all' : 'run'](sql, params, function(err, rows) {
|
|
217
|
+
if(err) {
|
|
218
|
+
const message = '数据操作失败,' + err.message + "\nSQL:" + that.format(sql, params);
|
|
219
|
+
that.$logger.sql(message);
|
|
220
|
+
that.$logger.error(message);
|
|
221
|
+
reject(new Error('DbError: ' + message));
|
|
222
|
+
} else {
|
|
223
|
+
that.$logger.sql('数据操作成功,SQL:' + that.format(sql, params));
|
|
224
|
+
if(isSelect || isTableInfo) {
|
|
225
|
+
resolve(rows);
|
|
226
|
+
} else {
|
|
227
|
+
resolve({
|
|
228
|
+
affectedRows: this.changes,
|
|
229
|
+
insertId: this.lastID
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if(!trans.has(that.ctx)) {
|
|
234
|
+
// SQLite不需要显式释放连接
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* 序列化sql语句
|
|
242
|
+
* @public
|
|
243
|
+
* @param {string} sql - sql语句或参数
|
|
244
|
+
* @param {*} params - sql参数
|
|
245
|
+
* @returns {string}
|
|
246
|
+
*/
|
|
247
|
+
format(sql, params) {
|
|
248
|
+
params || (params = []);
|
|
249
|
+
|
|
250
|
+
let formatted = sql;
|
|
251
|
+
for(let i = 0; i < params.length; i++) {
|
|
252
|
+
let value = params[i];
|
|
253
|
+
if (typeof value === 'string') {
|
|
254
|
+
value = "'" + value.replace(/'/g, "''") + "'";
|
|
255
|
+
} else if (value === null) {
|
|
256
|
+
value = 'NULL';
|
|
257
|
+
}
|
|
258
|
+
formatted = formatted.replace(/\?/, value);
|
|
259
|
+
}
|
|
260
|
+
return formatted;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* 获取数据表信息
|
|
265
|
+
* @public
|
|
266
|
+
* @param {string} tableName - 表名字
|
|
267
|
+
* @returns {Promise<FieldInfo[]>}
|
|
268
|
+
*/
|
|
269
|
+
async tableInfo(tableName) {
|
|
270
|
+
const columns = await this.query(`PRAGMA table_info(${tableName})`);
|
|
271
|
+
return columns.map(col => {
|
|
272
|
+
return {
|
|
273
|
+
Field: col.name,
|
|
274
|
+
Type: col.type,
|
|
275
|
+
Null: col.notnull === 1 ? 'NO' : 'YES',
|
|
276
|
+
Key: col.pk === 1 ? 'PRI' : '',
|
|
277
|
+
Default: col.dflt_value,
|
|
278
|
+
Extra: col.pk === 1 ? 'auto_increment' : '',
|
|
279
|
+
};
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
module.exports = Sqlite;
|
package/lib/db.js
CHANGED
|
@@ -3,29 +3,16 @@ const md5 = require('./utils/md5');
|
|
|
3
3
|
const Context = require('./context');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
+
* @typedef {import('../types').KoaCtx} KoaCtx
|
|
6
7
|
* @typedef {import('../types').Pagination} Pagination
|
|
7
8
|
* @typedef {import('../types').PaginationInstance} PaginationInstance
|
|
8
|
-
* @typedef {import('../types').Pool} Pool
|
|
9
|
-
* @typedef {import('../types').PoolConfig} PoolConfig
|
|
10
|
-
* @typedef {import('../types').PoolConnection} PoolConnection
|
|
11
|
-
* @typedef {import('../types').QueryOptions} QueryOptions
|
|
12
9
|
* @typedef {import('../types').OkPacket} OkPacket
|
|
13
10
|
* @typedef {import('../types').RowData} RowData
|
|
14
11
|
* @typedef {import('../types').ListData} ListData
|
|
15
12
|
* @typedef {import('../types').FieldInfo} FieldInfo
|
|
16
|
-
* @typedef {import('../types').
|
|
13
|
+
* @typedef {import('../types').SqlInstance} SqlInstance
|
|
17
14
|
*/
|
|
18
15
|
|
|
19
|
-
//连接池
|
|
20
|
-
/**
|
|
21
|
-
* @type {PoolMap}
|
|
22
|
-
*/
|
|
23
|
-
const pool = new Map();
|
|
24
|
-
//事务连接
|
|
25
|
-
const trans = new Map();
|
|
26
|
-
//事务嵌套
|
|
27
|
-
const nest = new Map();
|
|
28
|
-
|
|
29
16
|
/**
|
|
30
17
|
* @extends Context
|
|
31
18
|
*/
|
|
@@ -34,8 +21,8 @@ class Db extends Context
|
|
|
34
21
|
/**
|
|
35
22
|
* Initialize a new `Db`
|
|
36
23
|
* @public
|
|
37
|
-
* @param {
|
|
38
|
-
* @param {(string|
|
|
24
|
+
* @param {(object|KoaCtx)} [ctx]
|
|
25
|
+
* @param {(string|object)} [options] - 数据库配置标识或连接参数
|
|
39
26
|
*/
|
|
40
27
|
constructor(ctx, options) {
|
|
41
28
|
ctx = ctx || {};
|
|
@@ -48,6 +35,10 @@ class Db extends Context
|
|
|
48
35
|
*/
|
|
49
36
|
this._queryStr = '';
|
|
50
37
|
this._tableField = {};
|
|
38
|
+
/**
|
|
39
|
+
* @type {SqlInstance}
|
|
40
|
+
*/
|
|
41
|
+
this._sql = null;
|
|
51
42
|
this.connect(options);
|
|
52
43
|
}
|
|
53
44
|
|
|
@@ -78,28 +69,20 @@ class Db extends Context
|
|
|
78
69
|
/**
|
|
79
70
|
* 连接数据库连接池
|
|
80
71
|
* @public
|
|
81
|
-
* @param {(string|
|
|
72
|
+
* @param {(string|object)} config - 数据库配置标识或连接参数
|
|
82
73
|
* @returns {this}
|
|
83
74
|
*/
|
|
84
|
-
connect(
|
|
85
|
-
this._config = typeof
|
|
75
|
+
connect(config='default') {
|
|
76
|
+
this._config = typeof config === 'string' ? cfg_db[config] : config;
|
|
86
77
|
this.reset();
|
|
87
78
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
cur_pool = require('mysql').createPool(this._config);
|
|
96
|
-
break;
|
|
97
|
-
default:
|
|
98
|
-
//other database, please provide database driver and implement the connection method
|
|
99
|
-
cur_pool = this._config.connect(this._config);
|
|
100
|
-
}
|
|
101
|
-
pool.set(this._config, cur_pool);
|
|
102
|
-
this.$logger.sql(`连接池创建成功:{all: ${pool.size}}`);
|
|
79
|
+
if(this._config.connect) {
|
|
80
|
+
this._sql = this._config.connect(this._config);
|
|
81
|
+
} else {
|
|
82
|
+
const sqltype = this._config.type;
|
|
83
|
+
const Sql = require(`./db/${sqltype}.js`);
|
|
84
|
+
this._sql = new Sql(this.ctx, this.$logger);
|
|
85
|
+
this._sql.connect(this._config);
|
|
103
86
|
}
|
|
104
87
|
|
|
105
88
|
return this;
|
|
@@ -111,67 +94,7 @@ class Db extends Context
|
|
|
111
94
|
* @returns {Promise}
|
|
112
95
|
*/
|
|
113
96
|
async close() {
|
|
114
|
-
return
|
|
115
|
-
pool.has(this._config) && pool.get(this._config).end(err => {
|
|
116
|
-
if(err) {
|
|
117
|
-
const message = '连接池销毁失败:' + err.message;
|
|
118
|
-
this.$logger.sql(message);
|
|
119
|
-
this.$logger.error(message);
|
|
120
|
-
reject(new Error('DbError: ' + message));
|
|
121
|
-
} else {
|
|
122
|
-
pool.delete(this._config);
|
|
123
|
-
this.$logger.sql(`连接池销毁成功:{poolTotal: ${pool.size}}`);
|
|
124
|
-
resolve(this);
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* 释放数据库连接
|
|
132
|
-
* @public
|
|
133
|
-
* @param {PoolConnection} conn - 数据库连接
|
|
134
|
-
*/
|
|
135
|
-
release(conn) {
|
|
136
|
-
try {
|
|
137
|
-
conn.release();
|
|
138
|
-
this.$logger.sql('释放数据库连接!');
|
|
139
|
-
} catch(e) {
|
|
140
|
-
const message = '释放数据库出错:' + e.message;
|
|
141
|
-
this.$logger.sql(message);
|
|
142
|
-
this.$logger.error(message);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* 获取数据库连接
|
|
148
|
-
* @private
|
|
149
|
-
* @param {Pool} p
|
|
150
|
-
* @returns {Promise}
|
|
151
|
-
*/
|
|
152
|
-
async _creatConnect(p) {
|
|
153
|
-
return new Promise((resolve, reject) => {
|
|
154
|
-
p.getConnection((err, connection) => {
|
|
155
|
-
if(err) {
|
|
156
|
-
const message = '获取数据库连接失败:' + err.message;
|
|
157
|
-
this.$logger.sql(message);
|
|
158
|
-
this.$logger.error(message);
|
|
159
|
-
reject(new Error('DbError: ' + message));
|
|
160
|
-
} else {
|
|
161
|
-
this.$logger.sql(`获取数据库连接:{limit: ${p.config.connectionLimit}, all: ${p._allConnections.length}, acquiring: ${p._acquiringConnections.length}, free: ${p._freeConnections.length}, queue: ${p._connectionQueue.length}}`);
|
|
162
|
-
resolve(connection);
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* 获取数据库连接
|
|
170
|
-
* @private
|
|
171
|
-
* @returns {Promise<PoolConnection>}
|
|
172
|
-
*/
|
|
173
|
-
async _getConnect() {
|
|
174
|
-
return trans.get(this.ctx) || await this._creatConnect(pool.get(this._config));
|
|
97
|
+
return await this._sql.close();
|
|
175
98
|
}
|
|
176
99
|
|
|
177
100
|
/**
|
|
@@ -181,49 +104,7 @@ class Db extends Context
|
|
|
181
104
|
* @returns {Promise<string>}
|
|
182
105
|
*/
|
|
183
106
|
async startTrans(fun) {
|
|
184
|
-
|
|
185
|
-
trans.set(this.ctx, conn);
|
|
186
|
-
let trans_nest = nest.get(conn) || 0;
|
|
187
|
-
nest.set(conn, ++trans_nest);
|
|
188
|
-
if(trans_nest > 1) {
|
|
189
|
-
const message = `开启事务成功:{nest:${trans_nest}}`;
|
|
190
|
-
this.$logger.sql(message);
|
|
191
|
-
if(typeof fun === 'function') {
|
|
192
|
-
try {
|
|
193
|
-
await fun();
|
|
194
|
-
await this.commit();
|
|
195
|
-
} catch(e) {
|
|
196
|
-
await this.rollback();
|
|
197
|
-
throw e;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
return message;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return new Promise((resolve, reject) => {
|
|
204
|
-
conn.beginTransaction(async (err) => {
|
|
205
|
-
if(err) {
|
|
206
|
-
const message = '开启事务失败:' + err.message;
|
|
207
|
-
this.$logger.sql(message);
|
|
208
|
-
this.$logger.error(message);
|
|
209
|
-
reject(new Error('DbError: ' + message));
|
|
210
|
-
} else {
|
|
211
|
-
const message = '开启事务成功!';
|
|
212
|
-
this.$logger.sql(message);
|
|
213
|
-
if(typeof fun === 'function') {
|
|
214
|
-
try {
|
|
215
|
-
await fun();
|
|
216
|
-
await this.commit();
|
|
217
|
-
resolve('事务执行成功!');
|
|
218
|
-
} catch(e) {
|
|
219
|
-
await this.rollback();
|
|
220
|
-
reject(e);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
resolve(message);
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
});
|
|
107
|
+
return await this._sql.startTrans(fun);
|
|
227
108
|
}
|
|
228
109
|
|
|
229
110
|
/**
|
|
@@ -232,26 +113,7 @@ class Db extends Context
|
|
|
232
113
|
* @returns {Promise<string>}
|
|
233
114
|
*/
|
|
234
115
|
async rollback() {
|
|
235
|
-
|
|
236
|
-
const trans_nest = nest.get(conn) || 0;
|
|
237
|
-
if(trans_nest > 1) {
|
|
238
|
-
nest.set(conn, trans_nest - 1);
|
|
239
|
-
const message = `事务回滚成功:{nest:${trans_nest}}`;
|
|
240
|
-
this.$logger.sql(message);
|
|
241
|
-
return message;
|
|
242
|
-
} else {
|
|
243
|
-
nest.delete(conn);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return new Promise((resolve) => {
|
|
247
|
-
conn.rollback(() => {
|
|
248
|
-
trans.delete(this.ctx);
|
|
249
|
-
const message = '事务回滚成功!';
|
|
250
|
-
this.$logger.sql(message);
|
|
251
|
-
this.release(conn);
|
|
252
|
-
resolve(message);
|
|
253
|
-
});
|
|
254
|
-
});
|
|
116
|
+
return await this._sql.rollback();
|
|
255
117
|
}
|
|
256
118
|
|
|
257
119
|
/**
|
|
@@ -260,34 +122,7 @@ class Db extends Context
|
|
|
260
122
|
* @returns {Promise<string>}
|
|
261
123
|
*/
|
|
262
124
|
async commit() {
|
|
263
|
-
|
|
264
|
-
const trans_nest = nest.get(conn) || 0;
|
|
265
|
-
if(trans_nest > 1) {
|
|
266
|
-
nest.set(conn, trans_nest - 1);
|
|
267
|
-
const message = `事务提交成功:{nest:${trans_nest}}`;
|
|
268
|
-
this.$logger.sql(message);
|
|
269
|
-
return message;
|
|
270
|
-
} else {
|
|
271
|
-
nest.delete(conn);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
return new Promise((resolve, reject) => {
|
|
275
|
-
conn.commit((err) => {
|
|
276
|
-
if(err) {
|
|
277
|
-
const message = '事务提交失败:' + err.message;
|
|
278
|
-
this.$logger.sql(message);
|
|
279
|
-
this.$logger.error(message);
|
|
280
|
-
this.rollback();
|
|
281
|
-
reject(new Error('DbError: ' + message));
|
|
282
|
-
} else {
|
|
283
|
-
trans.delete(this.ctx);
|
|
284
|
-
const message = '事务提交成功!';
|
|
285
|
-
this.$logger.sql(message);
|
|
286
|
-
this.release(conn);
|
|
287
|
-
resolve(message);
|
|
288
|
-
}
|
|
289
|
-
});
|
|
290
|
-
});
|
|
125
|
+
return await this._sql.commit();
|
|
291
126
|
}
|
|
292
127
|
|
|
293
128
|
/**
|
|
@@ -302,27 +137,7 @@ class Db extends Context
|
|
|
302
137
|
params !== false && reset !== false && this.reset();
|
|
303
138
|
params || (params = []);
|
|
304
139
|
|
|
305
|
-
|
|
306
|
-
* @type {PoolConnection}
|
|
307
|
-
*/
|
|
308
|
-
const conn = await this._getConnect();
|
|
309
|
-
|
|
310
|
-
return new Promise((resolve, reject) => {
|
|
311
|
-
conn.query(sql, params, (err, data) => {
|
|
312
|
-
if(err) {
|
|
313
|
-
const message = '数据操作失败,' + err.message + "\r\nSQL:" + this.format(sql, params);
|
|
314
|
-
this.$logger.sql(message);
|
|
315
|
-
this.$logger.error(message);
|
|
316
|
-
reject(new Error('DbError: ' + message));
|
|
317
|
-
} else {
|
|
318
|
-
this.$logger.sql('数据操作成功,SQL:' + this.format(sql, params));
|
|
319
|
-
resolve(data);
|
|
320
|
-
}
|
|
321
|
-
if(!trans.has(this.ctx)) {
|
|
322
|
-
this.release(conn);
|
|
323
|
-
}
|
|
324
|
-
});
|
|
325
|
-
});
|
|
140
|
+
return await this._sql.query(sql, params);
|
|
326
141
|
}
|
|
327
142
|
|
|
328
143
|
/**
|
|
@@ -531,7 +346,7 @@ class Db extends Context
|
|
|
531
346
|
* 获取多条数据
|
|
532
347
|
* @public
|
|
533
348
|
* @param {object} condition - 查询条件
|
|
534
|
-
* @returns {Promise<ListData>}
|
|
349
|
+
* @returns {Promise<string|ListData>}
|
|
535
350
|
*/
|
|
536
351
|
async select(condition) {
|
|
537
352
|
condition && (this._options.where = [], this._options.where.push([condition]));
|
|
@@ -555,12 +370,12 @@ class Db extends Context
|
|
|
555
370
|
|
|
556
371
|
if(this._options.getSql) {
|
|
557
372
|
this._options.getSql = false;
|
|
558
|
-
return this.format(this._queryStr, params);
|
|
373
|
+
return this._sql.format(this._queryStr, params);
|
|
559
374
|
}
|
|
560
375
|
|
|
561
376
|
if(this._options.cache_time) {
|
|
562
377
|
const cache_time = this._options.cache_time;
|
|
563
|
-
const cache_key = md5(this.format(this._queryStr, params));
|
|
378
|
+
const cache_key = md5(this._sql.format(this._queryStr, params));
|
|
564
379
|
if(this.getCache(cache_key)) {
|
|
565
380
|
this.reset();
|
|
566
381
|
return this.getCache(cache_key);
|
|
@@ -675,6 +490,9 @@ class Db extends Context
|
|
|
675
490
|
return await this.select();
|
|
676
491
|
}
|
|
677
492
|
|
|
493
|
+
/**
|
|
494
|
+
* @type {ListData}
|
|
495
|
+
*/
|
|
678
496
|
const rows = await this.select();
|
|
679
497
|
const result = key ? {} : [];
|
|
680
498
|
rows.forEach(row => {
|
|
@@ -723,23 +541,19 @@ class Db extends Context
|
|
|
723
541
|
* 插入一条数据
|
|
724
542
|
* @public
|
|
725
543
|
* @param {object} data - 待插入数据
|
|
726
|
-
* @returns {Promise<OkPacket>}
|
|
544
|
+
* @returns {Promise<string|OkPacket>}
|
|
727
545
|
*/
|
|
728
546
|
async insert(data) {
|
|
729
547
|
data && (this._options.data = data);
|
|
730
548
|
|
|
731
|
-
let params = [];
|
|
732
549
|
const table = this._parseTable();
|
|
733
|
-
|
|
734
550
|
await this._filterData();
|
|
551
|
+
const [sql, params] = this._parseInsertData();
|
|
735
552
|
|
|
736
|
-
|
|
737
|
-
params = params.concat(data[1]);
|
|
738
|
-
|
|
739
|
-
this._queryStr = `insert into ${table} set ${data[0]}`;
|
|
553
|
+
this._queryStr = `insert into ${table} ${sql}`;
|
|
740
554
|
if(this._options.getSql) {
|
|
741
555
|
this._options.getSql = false;
|
|
742
|
-
return this.format(this._queryStr, params);
|
|
556
|
+
return this._sql.format(this._queryStr, params);
|
|
743
557
|
}
|
|
744
558
|
return await this.query(this._queryStr, params);
|
|
745
559
|
}
|
|
@@ -749,32 +563,28 @@ class Db extends Context
|
|
|
749
563
|
* @public
|
|
750
564
|
* @param {object} data - 更新数据
|
|
751
565
|
* @param {object} condition - 更新条件
|
|
752
|
-
* @returns {Promise<OkPacket>}
|
|
566
|
+
* @returns {Promise<string|OkPacket>}
|
|
753
567
|
*/
|
|
754
568
|
async update(data, condition) {
|
|
755
569
|
data && (this._options.data = data);
|
|
756
570
|
condition && (this._options.where = [], this._options.where.push([condition]));
|
|
757
571
|
|
|
758
|
-
let params = [];
|
|
759
572
|
const table = this._parseTable();
|
|
760
|
-
|
|
761
573
|
await this._filterData();
|
|
574
|
+
const [sql, dataParams] = this._parseUpdateData();
|
|
762
575
|
|
|
763
|
-
|
|
764
|
-
params = params.concat(data[1]);
|
|
765
|
-
|
|
766
|
-
const where = this._parseWhere();
|
|
576
|
+
const [where, whereParams] = this._parseWhere();
|
|
767
577
|
if(!where[0]) {
|
|
768
578
|
const message = 'update方法必须传入where参数';
|
|
769
579
|
this.$logger.sql(message);
|
|
770
580
|
throw new Error('DbError: ' + message);
|
|
771
581
|
}
|
|
772
|
-
params =
|
|
582
|
+
const params = [...dataParams, ...whereParams];
|
|
773
583
|
|
|
774
|
-
this._queryStr = `update ${table} set ${
|
|
584
|
+
this._queryStr = `update ${table} set ${sql} ${where}`;
|
|
775
585
|
if(this._options.getSql) {
|
|
776
586
|
this._options.getSql = false;
|
|
777
|
-
return this.format(this._queryStr, params);
|
|
587
|
+
return this._sql.format(this._queryStr, params);
|
|
778
588
|
}
|
|
779
589
|
return await this.query(this._queryStr, params);
|
|
780
590
|
}
|
|
@@ -784,7 +594,7 @@ class Db extends Context
|
|
|
784
594
|
* @public
|
|
785
595
|
* @param {string} field - 字段
|
|
786
596
|
* @param {number} [step=1] - 增加值,默认1
|
|
787
|
-
* @returns {Promise<OkPacket>}
|
|
597
|
+
* @returns {Promise<string|OkPacket>}
|
|
788
598
|
*/
|
|
789
599
|
async inc(field, step) {
|
|
790
600
|
return await this.update({[field]: ['inc', step]});
|
|
@@ -795,7 +605,7 @@ class Db extends Context
|
|
|
795
605
|
* @public
|
|
796
606
|
* @param {string} field - 字段
|
|
797
607
|
* @param {number} [step=1] - 减少值,默认1
|
|
798
|
-
* @returns {Promise<OkPacket>}
|
|
608
|
+
* @returns {Promise<string|OkPacket>}
|
|
799
609
|
*/
|
|
800
610
|
async dec(field, step) {
|
|
801
611
|
return await this.update({[field]: ['dec', step]});
|
|
@@ -806,7 +616,7 @@ class Db extends Context
|
|
|
806
616
|
* @public
|
|
807
617
|
* @param {string} field - 字段
|
|
808
618
|
* @param {string} value - 自定义表达式
|
|
809
|
-
* @returns {Promise<OkPacket>}
|
|
619
|
+
* @returns {Promise<string|OkPacket>}
|
|
810
620
|
*/
|
|
811
621
|
async exp(field, value) {
|
|
812
622
|
return await this.update({[field]: ['exp', value]});
|
|
@@ -815,8 +625,8 @@ class Db extends Context
|
|
|
815
625
|
/**
|
|
816
626
|
* 删除数据
|
|
817
627
|
* @public
|
|
818
|
-
* @param {object} condition -
|
|
819
|
-
* @returns {Promise<OkPacket>}
|
|
628
|
+
* @param {object} condition - 删除条件
|
|
629
|
+
* @returns {Promise<string|OkPacket>}
|
|
820
630
|
*/
|
|
821
631
|
async delete(condition) {
|
|
822
632
|
condition && (this._options.where = [], this._options.where.push([condition]));
|
|
@@ -834,7 +644,7 @@ class Db extends Context
|
|
|
834
644
|
this._queryStr = `delete from ${table} ${where[0]}`;
|
|
835
645
|
if(this._options.getSql) {
|
|
836
646
|
this._options.getSql = false;
|
|
837
|
-
return this.format(this._queryStr, params);
|
|
647
|
+
return this._sql.format(this._queryStr, params);
|
|
838
648
|
}
|
|
839
649
|
return await this.query(this._queryStr, params);
|
|
840
650
|
}
|
|
@@ -845,18 +655,18 @@ class Db extends Context
|
|
|
845
655
|
* @param {string} sql - sql语句或参数
|
|
846
656
|
* @param {*} params - sql参数
|
|
847
657
|
* @param {*} [reset=true] - 是否重置参数
|
|
848
|
-
* @returns {Promise<
|
|
658
|
+
* @returns {Promise<string|OkPacket|ListData|RowData>}
|
|
849
659
|
*/
|
|
850
660
|
async execute(sql, params, reset=true) {
|
|
851
661
|
this._queryStr = sql;
|
|
852
662
|
if(this._options.getSql) {
|
|
853
663
|
this._options.getSql = false;
|
|
854
|
-
return this.format(this._queryStr, params);
|
|
664
|
+
return this._sql.format(this._queryStr, params);
|
|
855
665
|
}
|
|
856
666
|
|
|
857
667
|
if(this._options.cache_time) {
|
|
858
668
|
const cache_time = this._options.cache_time;
|
|
859
|
-
const cache_key = md5(this.format(this._queryStr, params));
|
|
669
|
+
const cache_key = md5(this._sql.format(this._queryStr, params));
|
|
860
670
|
if(this.getCache(cache_key)) {
|
|
861
671
|
return this.getCache(cache_key);
|
|
862
672
|
}
|
|
@@ -876,7 +686,7 @@ class Db extends Context
|
|
|
876
686
|
async tableInfo(table) {
|
|
877
687
|
const get_sql = this._options.getSql;
|
|
878
688
|
this._options.getSql = false;
|
|
879
|
-
const table_info = await this.table(table).
|
|
689
|
+
const table_info = await this.table(table)._sql.tableInfo(this._parseTable());
|
|
880
690
|
this._options.getSql = get_sql;
|
|
881
691
|
return table_info;
|
|
882
692
|
}
|
|
@@ -892,18 +702,6 @@ class Db extends Context
|
|
|
892
702
|
return table_info.map(item => item.Field);
|
|
893
703
|
}
|
|
894
704
|
|
|
895
|
-
/**
|
|
896
|
-
* 序列化sql语句
|
|
897
|
-
* @public
|
|
898
|
-
* @param {string} sql - sql语句或参数
|
|
899
|
-
* @param {*} params - sql参数
|
|
900
|
-
* @returns {string}
|
|
901
|
-
*/
|
|
902
|
-
format(sql, params) {
|
|
903
|
-
params || (params = []);
|
|
904
|
-
return require('mysql').format(sql, params);
|
|
905
|
-
}
|
|
906
|
-
|
|
907
705
|
_parseTable() {
|
|
908
706
|
const table = this._table.replace(' ', '` `');
|
|
909
707
|
return `\`${this._options.prefix}${table}\``;
|
|
@@ -1004,7 +802,21 @@ class Db extends Context
|
|
|
1004
802
|
return order;
|
|
1005
803
|
}
|
|
1006
804
|
|
|
1007
|
-
|
|
805
|
+
_parseInsertData() {
|
|
806
|
+
const fields = [];
|
|
807
|
+
const values = [];
|
|
808
|
+
const params = [];
|
|
809
|
+
Object.keys(this._options.data).forEach(key => {
|
|
810
|
+
const field = '`' + key.replace('.', '`.`') + '`';
|
|
811
|
+
fields.push(field);
|
|
812
|
+
values.push('?');
|
|
813
|
+
const value = this._options.data[key];
|
|
814
|
+
params.push(value);
|
|
815
|
+
});
|
|
816
|
+
return [`(${fields.join(', ')}) values (${values.join(', ')})`, params];
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
_parseUpdateData() {
|
|
1008
820
|
let data = '';
|
|
1009
821
|
const params = [];
|
|
1010
822
|
Object.keys(this._options.data).forEach(key => {
|
package/lib/request.js
CHANGED
package/package.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jj.js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "A super simple lightweight NodeJS MVC framework(一个超级简单轻量的NodeJS MVC框架)",
|
|
5
5
|
"main": "jj.js",
|
|
6
|
-
"scripts": {
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "node ./test/server.js"
|
|
8
|
+
},
|
|
7
9
|
"repository": {
|
|
8
10
|
"type": "git",
|
|
9
11
|
"url": "git+https://github.com/yafoo/jj.js.git"
|
|
@@ -28,6 +30,7 @@
|
|
|
28
30
|
"koa-body": "^6.0.1",
|
|
29
31
|
"koa-static": "^5.0.0",
|
|
30
32
|
"mysql": "^2.18.1",
|
|
33
|
+
"sqlite3": "^5.1.7",
|
|
31
34
|
"watch": "^1.0.2"
|
|
32
35
|
},
|
|
33
36
|
"engines": {
|
package/types.js
CHANGED