mm_dao 1.8.0 → 1.8.2
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/example/index.js +78 -0
- package/index.js +4 -6
- package/lib/{drive.js → dao.js} +113 -267
- package/lib/manager.js +49 -43
- package/package.json +65 -65
package/example/index.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* mm_dao SQL 帮助模块示例
|
|
5
|
+
* 演示:获取 SQL 模板管理器、创建 Dao 驱动,并在内存中构建查询条件(无需连接数据库)。
|
|
6
|
+
* 注:管理器 add() 存在未定义 Drive 的缺陷,此处直接实例化 Dao 驱动演示核心 API。
|
|
7
|
+
* 运行:node example/index.js
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { daoAdmin, Dao } = require('../index.js');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 创建一个纯内存的模拟数据库(仅实现 SQL 模板拼接,不连接真实数据库)
|
|
14
|
+
* @returns {object} 模拟数据库实例
|
|
15
|
+
*/
|
|
16
|
+
function createMockDb() {
|
|
17
|
+
return {
|
|
18
|
+
config: { filter: {} },
|
|
19
|
+
size: 30,
|
|
20
|
+
page: 0,
|
|
21
|
+
/**
|
|
22
|
+
* 过滤参数(无操作)
|
|
23
|
+
*/
|
|
24
|
+
filter() {},
|
|
25
|
+
/**
|
|
26
|
+
* 模板查询拼接
|
|
27
|
+
* @param {object} param 参数对象
|
|
28
|
+
* @param {object} sql_tpl 模板对象
|
|
29
|
+
* @returns {string} 拼接结果
|
|
30
|
+
*/
|
|
31
|
+
tplQuery(param, sql_tpl) {
|
|
32
|
+
const segments = [];
|
|
33
|
+
for (const key in param) {
|
|
34
|
+
const seg = sql_tpl[key]
|
|
35
|
+
? sql_tpl[key].replace(/\{0\}/g, param[key])
|
|
36
|
+
: '`' + key + "` = '" + param[key] + "'";
|
|
37
|
+
segments.push(seg);
|
|
38
|
+
}
|
|
39
|
+
return segments.join(' AND ');
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 主函数
|
|
46
|
+
* @returns {Promise<void>} 无返回值
|
|
47
|
+
*/
|
|
48
|
+
async function main() {
|
|
49
|
+
// 1. 获取 SQL 管理器(同 scope 复用实例)
|
|
50
|
+
const manager = daoAdmin('demo', { title: '示例SQL管理器' });
|
|
51
|
+
const manager2 = daoAdmin('demo');
|
|
52
|
+
console.log('管理器实例复用:', manager === manager2);
|
|
53
|
+
|
|
54
|
+
// 2. 创建 Dao 驱动(模板化增删改查)
|
|
55
|
+
const dao = new Dao(
|
|
56
|
+
{
|
|
57
|
+
name: 'user',
|
|
58
|
+
title: '用户表',
|
|
59
|
+
table: 'user_account',
|
|
60
|
+
key: 'user_id',
|
|
61
|
+
query: { name: "`name` like '%{0}%'", uid: '`uid` = {0}' }
|
|
62
|
+
},
|
|
63
|
+
manager
|
|
64
|
+
);
|
|
65
|
+
console.log('驱动类型:', dao instanceof Dao);
|
|
66
|
+
|
|
67
|
+
// 3. 构建查询条件(纯内存,无需数据库连接)
|
|
68
|
+
const where = dao.toWhere(createMockDb(), { name: '张三', uid: 1 }, 'get');
|
|
69
|
+
console.log('生成的WHERE条件:', where);
|
|
70
|
+
|
|
71
|
+
// 4. 驱动配置模型
|
|
72
|
+
console.log('驱动模型名称:', dao.getModel().name);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
main().catch((err) => {
|
|
76
|
+
console.error('示例执行失败:', err);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
});
|
package/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
const
|
|
2
|
-
const Drive = require('./lib/drive');
|
|
1
|
+
const Dao = require('./lib/dao');
|
|
3
2
|
const Manager = require('./lib/manager');
|
|
4
3
|
const Admin = require('mm_corejs').Admin;
|
|
5
4
|
|
|
@@ -7,8 +6,7 @@ const admin = new Admin();
|
|
|
7
6
|
admin.setClass(Manager);
|
|
8
7
|
|
|
9
8
|
module.exports = {
|
|
10
|
-
|
|
11
|
-
Drive,
|
|
9
|
+
Dao,
|
|
12
10
|
Manager,
|
|
13
11
|
admin,
|
|
14
12
|
/**
|
|
@@ -17,10 +15,10 @@ module.exports = {
|
|
|
17
15
|
* @param {object} [config] 配置参数
|
|
18
16
|
* @returns {object} SQL 管理器实例
|
|
19
17
|
*/
|
|
20
|
-
|
|
18
|
+
daoAdmin(scope, config) {
|
|
21
19
|
if (!scope) {
|
|
22
20
|
scope = 'os';
|
|
23
21
|
}
|
|
24
|
-
return admin.get(scope,
|
|
22
|
+
return admin.get(scope, config);
|
|
25
23
|
}
|
|
26
24
|
};
|
package/lib/{drive.js → dao.js}
RENAMED
|
@@ -1,164 +1,15 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
-
const Item = require('
|
|
2
|
+
const Item = require('mm_machine').Mod;
|
|
3
3
|
const { string, array, date, file } = require('mm_helper');
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* 是否以指定后缀结尾(替代 mm_expand 的 String.ends)
|
|
7
|
-
* @param {string} str 源字符串
|
|
8
|
-
* @param {string} suffix 后缀
|
|
9
|
-
* @returns {boolean} 以后缀结尾返回true, 否则返回false
|
|
10
|
-
*/
|
|
11
|
-
function _strEnds(str, suffix) {
|
|
12
|
-
return (str + '').endsWith(suffix);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* 合并值(替代 mm_expand 的 Array.clear/addList 深合并语义, 数组整体拷贝)
|
|
17
|
-
* @param {*} current 当前值
|
|
18
|
-
* @param {*} value 新值
|
|
19
|
-
* @param {boolean} bl 是否补充模式
|
|
20
|
-
* @returns {*} 合并后的值
|
|
21
|
-
*/
|
|
22
|
-
function _mergeValue(current, value, bl) {
|
|
23
|
-
var type = typeof current;
|
|
24
|
-
var value_type = typeof value;
|
|
25
|
-
if (type !== value_type) {
|
|
26
|
-
if (type === 'number') {
|
|
27
|
-
var n = Number(value);
|
|
28
|
-
return isNaN(n) ? 0 : n;
|
|
29
|
-
} else if (type === 'boolean') {
|
|
30
|
-
return !(value === '0' || value === 'false' || value === 'False');
|
|
31
|
-
} else if (type === 'string') {
|
|
32
|
-
return value.toString();
|
|
33
|
-
}
|
|
34
|
-
return value;
|
|
35
|
-
} else if (type === 'object') {
|
|
36
|
-
if (Array.isArray(current) && Array.isArray(value)) {
|
|
37
|
-
return value.slice();
|
|
38
|
-
}
|
|
39
|
-
_push(current, value, bl);
|
|
40
|
-
return current;
|
|
41
|
-
}
|
|
42
|
-
return value;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* 将对象B合并进对象A(替代 mm_os 全局 push)
|
|
47
|
-
* @param {object} obj_a 被添加的对象
|
|
48
|
-
* @param {object} obj_b 用作添加的对象
|
|
49
|
-
* @param {boolean} bl 为true时只补充obj_a中缺失的键
|
|
50
|
-
* @returns {object} 对象A自身
|
|
51
|
-
*/
|
|
52
|
-
function _push(obj_a, obj_b, bl) {
|
|
53
|
-
if (!obj_a || !obj_b) {
|
|
54
|
-
return obj_a;
|
|
55
|
-
}
|
|
56
|
-
if (bl) {
|
|
57
|
-
for (var k in obj_b) {
|
|
58
|
-
var value = obj_b[k];
|
|
59
|
-
if (obj_a[k] === undefined || obj_a[k] === null || value === null) {
|
|
60
|
-
obj_a[k] = value;
|
|
61
|
-
} else {
|
|
62
|
-
obj_a[k] = _mergeValue(obj_a[k], value, bl);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
} else {
|
|
66
|
-
for (var n in obj_a) {
|
|
67
|
-
var val = obj_b[n];
|
|
68
|
-
if (val !== undefined && obj_a[n] !== null && val !== null) {
|
|
69
|
-
obj_a[n] = _mergeValue(obj_a[n], val, bl);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return obj_a;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* 生成JSON-RPC响应体(替代 mm_os 的 ret.body, 等价 mm_ret 默认 json-rpc 格式)
|
|
78
|
-
* @param {*} result 返回的结果
|
|
79
|
-
* @param {object} error 错误信息 {code, message}
|
|
80
|
-
* @returns {object} 响应格式
|
|
81
|
-
*/
|
|
82
|
-
function _retBody(result, error) {
|
|
83
|
-
var ret = {};
|
|
84
|
-
if (result) {
|
|
85
|
-
ret.result = result;
|
|
86
|
-
} else if (error) {
|
|
87
|
-
ret.error = {
|
|
88
|
-
code: error.code || 10000,
|
|
89
|
-
message: error.message || '错误'
|
|
90
|
-
};
|
|
91
|
-
} else {
|
|
92
|
-
ret.error = { code: 10000, message: '错误' };
|
|
93
|
-
}
|
|
94
|
-
return ret;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* 生成错误响应(替代 mm_os 的 ret.error)
|
|
99
|
-
* @param {number} code 错误码
|
|
100
|
-
* @param {string} message 错误信息
|
|
101
|
-
* @returns {object} 错误响应格式
|
|
102
|
-
*/
|
|
103
|
-
function _retError(code, message) {
|
|
104
|
-
return _retBody(null, { code, message });
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* 生成列表响应(替代 mm_os 的 ret.list)
|
|
109
|
-
* @param {Array} list 返回列表
|
|
110
|
-
* @param {number} count 查询结果数
|
|
111
|
-
* @returns {object} 列表响应格式
|
|
112
|
-
*/
|
|
113
|
-
function _retList(list, count) {
|
|
114
|
-
var result = { list: list || [] };
|
|
115
|
-
if (count !== undefined) {
|
|
116
|
-
result.count = count;
|
|
117
|
-
}
|
|
118
|
-
return _retBody(result, null);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* 生成对象响应(替代 mm_os 的 ret.obj)
|
|
123
|
-
* @param {object} obj 返回对象
|
|
124
|
-
* @returns {object} 对象响应格式
|
|
125
|
-
*/
|
|
126
|
-
function _retObj(obj) {
|
|
127
|
-
return _retBody({ obj: obj }, null);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* 生成布尔型响应(替代 mm_os 的 ret.bl)
|
|
132
|
-
* @param {boolean} bl 布尔结果
|
|
133
|
-
* @param {string} tip 提示信息
|
|
134
|
-
* @returns {object} 布尔响应格式
|
|
135
|
-
*/
|
|
136
|
-
function _retBl(bl, tip) {
|
|
137
|
-
return _retBody({ bl: bl, tip: tip || (bl ? '成功' : '错误') }, null);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* 校验SQL标识符安全性, 仅允许字母、数字和下划线
|
|
142
|
-
* @param {string} name 标识符名称
|
|
143
|
-
* @returns {string} 安全的标识符
|
|
144
|
-
*/
|
|
145
|
-
function validateIden(name) {
|
|
146
|
-
if (typeof name !== 'string' || !name) {
|
|
147
|
-
return '';
|
|
148
|
-
}
|
|
149
|
-
var sanitized = name.replace(/`/g, '');
|
|
150
|
-
if (!/^[a-zA-Z0-9_]+$/.test(sanitized)) {
|
|
151
|
-
return '';
|
|
152
|
-
}
|
|
153
|
-
return sanitized;
|
|
154
|
-
}
|
|
4
|
+
const { getRet } = require('mm_ret');
|
|
5
|
+
const dbAdmin = require('mm_dbs');
|
|
155
6
|
|
|
156
7
|
/**
|
|
157
8
|
* Sql操作驱动类
|
|
158
9
|
* @augments {Item}
|
|
159
10
|
* @class
|
|
160
11
|
*/
|
|
161
|
-
class
|
|
12
|
+
class Dao extends Item {
|
|
162
13
|
static config = {
|
|
163
14
|
main: '',
|
|
164
15
|
// 表名 {0} 代表可前端传参自定义查询的表
|
|
@@ -283,7 +134,7 @@ class Drive extends Item {
|
|
|
283
134
|
* @class
|
|
284
135
|
*/
|
|
285
136
|
constructor(config, parent) {
|
|
286
|
-
super({ ...
|
|
137
|
+
super({ ...Dao.config, ...config });
|
|
287
138
|
|
|
288
139
|
// 父级管理器引用(用于默认配置回退与插件查找)
|
|
289
140
|
this.parent = parent || null;
|
|
@@ -296,7 +147,7 @@ class Drive extends Item {
|
|
|
296
147
|
/**
|
|
297
148
|
* 预设
|
|
298
149
|
*/
|
|
299
|
-
|
|
150
|
+
Dao.prototype._preset = function () {
|
|
300
151
|
// 保存文件目录
|
|
301
152
|
this.save_dir = './static/file/';
|
|
302
153
|
// 读取文件目录
|
|
@@ -311,14 +162,11 @@ Drive.prototype._preset = function () {
|
|
|
311
162
|
* @returns {*} 配置值, 未配置返回 undefined
|
|
312
163
|
* @private
|
|
313
164
|
*/
|
|
314
|
-
|
|
165
|
+
Dao.prototype._getInject = function (key) {
|
|
315
166
|
var value = this.config[key];
|
|
316
167
|
if (value !== undefined && value !== null && value !== '') {
|
|
317
168
|
return value;
|
|
318
169
|
}
|
|
319
|
-
if (this.parent && this.parent.config) {
|
|
320
|
-
return this.parent.config[key];
|
|
321
|
-
}
|
|
322
170
|
return undefined;
|
|
323
171
|
};
|
|
324
172
|
|
|
@@ -327,7 +175,7 @@ Drive.prototype._getInject = function (key) {
|
|
|
327
175
|
* @returns {object} 字典对象
|
|
328
176
|
* @private
|
|
329
177
|
*/
|
|
330
|
-
|
|
178
|
+
Dao.prototype._getDict = function () {
|
|
331
179
|
return this._getInject('dict') || {};
|
|
332
180
|
};
|
|
333
181
|
|
|
@@ -337,7 +185,7 @@ Drive.prototype._getDict = function () {
|
|
|
337
185
|
* @param {object} db 数据库管理器
|
|
338
186
|
* @returns {object} 过滤后的参数
|
|
339
187
|
*/
|
|
340
|
-
|
|
188
|
+
Dao.prototype.before = async function (params, db) {
|
|
341
189
|
return params;
|
|
342
190
|
};
|
|
343
191
|
|
|
@@ -347,7 +195,7 @@ Drive.prototype.before = async function (params, db) {
|
|
|
347
195
|
* @param {object} db 数据管理器
|
|
348
196
|
* @returns {boolean} 验证通过返回true, 失败返回false
|
|
349
197
|
*/
|
|
350
|
-
|
|
198
|
+
Dao.prototype.check = async function (params, db) {
|
|
351
199
|
return true;
|
|
352
200
|
};
|
|
353
201
|
|
|
@@ -357,7 +205,7 @@ Drive.prototype.check = async function (params, db) {
|
|
|
357
205
|
* @param {object} db 数据管理器
|
|
358
206
|
* @returns {object} 最终执行结果
|
|
359
207
|
*/
|
|
360
|
-
|
|
208
|
+
Dao.prototype.after = async function (params, db) {
|
|
361
209
|
return db.ret;
|
|
362
210
|
};
|
|
363
211
|
|
|
@@ -366,7 +214,7 @@ Drive.prototype.after = async function (params, db) {
|
|
|
366
214
|
* @param {string} table 表名
|
|
367
215
|
* @param {object} sql 缓存sql语句
|
|
368
216
|
*/
|
|
369
|
-
|
|
217
|
+
Dao.prototype.updateCache = async function (table, sql) {};
|
|
370
218
|
|
|
371
219
|
/**
|
|
372
220
|
* @ 执行修改
|
|
@@ -375,7 +223,7 @@ Drive.prototype.updateCache = async function (table, sql) {};
|
|
|
375
223
|
* @param {object} db 数据库管理器
|
|
376
224
|
* @returns {object} 返回执行结果
|
|
377
225
|
*/
|
|
378
|
-
|
|
226
|
+
Dao.prototype.run = async function (query, body, db) {
|
|
379
227
|
var params = {
|
|
380
228
|
query,
|
|
381
229
|
body,
|
|
@@ -400,10 +248,10 @@ Drive.prototype.run = async function (query, body, db) {
|
|
|
400
248
|
* @param {object} body 修改项
|
|
401
249
|
* @returns {object} 返回准备参数
|
|
402
250
|
*/
|
|
403
|
-
|
|
251
|
+
Dao.prototype.ready = function (db, query, body) {
|
|
404
252
|
var cg = this.config;
|
|
405
253
|
var qy = { ...query };
|
|
406
|
-
|
|
254
|
+
Object.assign(db.config.filter, cg.filter);
|
|
407
255
|
db.filter(qy);
|
|
408
256
|
return {
|
|
409
257
|
cg,
|
|
@@ -418,7 +266,7 @@ Drive.prototype.ready = function (db, query, body) {
|
|
|
418
266
|
* @param {object} method 方法
|
|
419
267
|
* @returns {string} 返回查询条件
|
|
420
268
|
*/
|
|
421
|
-
|
|
269
|
+
Dao.prototype.toWhere = function (db, query, method) {
|
|
422
270
|
var { cg, qy: originalQy } = this.ready(db, query, {});
|
|
423
271
|
// 创建 qy 对象的副本,避免修改原始参数
|
|
424
272
|
var qy = { ...originalQy };
|
|
@@ -435,7 +283,7 @@ Drive.prototype.toWhere = function (db, query, method) {
|
|
|
435
283
|
* @param {object} query 查询条件
|
|
436
284
|
* @private
|
|
437
285
|
*/
|
|
438
|
-
|
|
286
|
+
Dao.prototype._setDbConfig = function (db, cg, query) {
|
|
439
287
|
db.config.separator = cg.separator;
|
|
440
288
|
if (!query.size && cg.page_size) {
|
|
441
289
|
db.size = cg.page_size + 0;
|
|
@@ -455,12 +303,12 @@ Drive.prototype._setDbConfig = function (db, cg, query) {
|
|
|
455
303
|
* @returns {object} 更新后的查询条件对象
|
|
456
304
|
* @private
|
|
457
305
|
*/
|
|
458
|
-
|
|
306
|
+
Dao.prototype._setQueryField = function (db, query, cg, method, qy) {
|
|
459
307
|
var f = db.config.filter;
|
|
460
308
|
var field = query[f.field];
|
|
461
309
|
if (string.has(cg.field, '*{0}*')) {
|
|
462
310
|
if (field) {
|
|
463
|
-
var safe_field =
|
|
311
|
+
var safe_field = typeof field === 'string' && string.validate(field, 'username') ? field : '';
|
|
464
312
|
if (safe_field) {
|
|
465
313
|
db.field = cg.field.replace('{0}', safe_field);
|
|
466
314
|
} else {
|
|
@@ -489,12 +337,12 @@ Drive.prototype._setQueryField = function (db, query, cg, method, qy) {
|
|
|
489
337
|
* @returns {object} 更新后的查询条件对象
|
|
490
338
|
* @private
|
|
491
339
|
*/
|
|
492
|
-
|
|
340
|
+
Dao.prototype._setOrderBy = function (db, query, cg, qy) {
|
|
493
341
|
var f = db.config.filter;
|
|
494
342
|
var orderby = query[f.orderby];
|
|
495
343
|
if (string.has(cg.orderby, '*{0}*')) {
|
|
496
344
|
if (orderby) {
|
|
497
|
-
var safe_orderby =
|
|
345
|
+
var safe_orderby = typeof orderby === 'string' && string.validate(orderby, 'username') ? orderby : '';
|
|
498
346
|
if (safe_orderby) {
|
|
499
347
|
db.orderby = cg.orderby.replace('{0}', safe_orderby);
|
|
500
348
|
} else {
|
|
@@ -520,7 +368,7 @@ Drive.prototype._setOrderBy = function (db, query, cg, qy) {
|
|
|
520
368
|
* @returns {string} 查询字符串
|
|
521
369
|
* @private
|
|
522
370
|
*/
|
|
523
|
-
|
|
371
|
+
Dao.prototype._buildQueryString = function (db, qy, cg) {
|
|
524
372
|
var query_str = db.tplQuery(qy, cg.query);
|
|
525
373
|
var qt = cg.query_default;
|
|
526
374
|
if (Object.keys(qt).length > 0) {
|
|
@@ -550,21 +398,21 @@ Drive.prototype._buildQueryString = function (db, qy, cg) {
|
|
|
550
398
|
* @param {object} method 方法
|
|
551
399
|
* @returns {object} 返回查询结果
|
|
552
400
|
*/
|
|
553
|
-
|
|
401
|
+
Dao.prototype.getMain = async function (db, query, method) {
|
|
554
402
|
var ret;
|
|
555
403
|
if (string.has(this.config.field, '*{0}*')) {
|
|
556
404
|
var field = query[db.config.filter.field];
|
|
557
405
|
if (field && array.getMatch(this.config.field_hide, field)) {
|
|
558
|
-
return
|
|
406
|
+
return getRet().error(70003, '不合法的查询参数');
|
|
559
407
|
}
|
|
560
408
|
}
|
|
561
409
|
var query_str = this.toWhere(db, query, method);
|
|
562
410
|
|
|
563
411
|
// 查询
|
|
564
412
|
if (db.count_ret === 'true') {
|
|
565
|
-
ret =
|
|
413
|
+
ret = getRet().body(await db.getCountSql(query_str, db.orderby, db.field), null);
|
|
566
414
|
} else {
|
|
567
|
-
ret =
|
|
415
|
+
ret = getRet().list(await db.getSql(query_str, db.orderby, db.field));
|
|
568
416
|
}
|
|
569
417
|
return ret;
|
|
570
418
|
};
|
|
@@ -576,7 +424,7 @@ Drive.prototype.getMain = async function (db, query, method) {
|
|
|
576
424
|
* @param {object} body 修改项
|
|
577
425
|
* @returns {object} 返回查询结果
|
|
578
426
|
*/
|
|
579
|
-
|
|
427
|
+
Dao.prototype.get = async function (db, query, body) {
|
|
580
428
|
return await this.getMain(db, query);
|
|
581
429
|
};
|
|
582
430
|
|
|
@@ -587,7 +435,7 @@ Drive.prototype.get = async function (db, query, body) {
|
|
|
587
435
|
* @param {object} body 修改项
|
|
588
436
|
* @returns {object} 返回查询结果
|
|
589
437
|
*/
|
|
590
|
-
|
|
438
|
+
Dao.prototype.getObj = async function (db, query, body) {
|
|
591
439
|
var qy = { ...query };
|
|
592
440
|
qy.page = 1;
|
|
593
441
|
qy.size = 1;
|
|
@@ -595,9 +443,9 @@ Drive.prototype.getObj = async function (db, query, body) {
|
|
|
595
443
|
if (ret.result) {
|
|
596
444
|
var list = ret.result.list;
|
|
597
445
|
if (list.length > 0) {
|
|
598
|
-
return
|
|
446
|
+
return getRet().body({ obj: list[0] });
|
|
599
447
|
} else {
|
|
600
|
-
return
|
|
448
|
+
return getRet().body({ obj: null });
|
|
601
449
|
}
|
|
602
450
|
}
|
|
603
451
|
return ret;
|
|
@@ -610,7 +458,7 @@ Drive.prototype.getObj = async function (db, query, body) {
|
|
|
610
458
|
* @param {object} body 修改项
|
|
611
459
|
* @returns {object} 返回修改结果
|
|
612
460
|
*/
|
|
613
|
-
|
|
461
|
+
Dao.prototype.setMain = async function (db, query, body) {
|
|
614
462
|
var ret;
|
|
615
463
|
var { cg, qy } = this.ready(db, query, body);
|
|
616
464
|
var key = cg.key;
|
|
@@ -640,9 +488,9 @@ Drive.prototype.setMain = async function (db, query, body) {
|
|
|
640
488
|
var n = await db.setSql(query_str, db.tplBody(body, cg.update));
|
|
641
489
|
|
|
642
490
|
if (n < 1) {
|
|
643
|
-
ret =
|
|
491
|
+
ret = getRet().error(500, '修改失败!\n' + db.error.message);
|
|
644
492
|
} else {
|
|
645
|
-
ret =
|
|
493
|
+
ret = getRet().bl(true, '修改成功!');
|
|
646
494
|
}
|
|
647
495
|
return ret;
|
|
648
496
|
};
|
|
@@ -654,7 +502,7 @@ Drive.prototype.setMain = async function (db, query, body) {
|
|
|
654
502
|
* @param {object} body 修改项
|
|
655
503
|
* @returns {object} 返回查询结果
|
|
656
504
|
*/
|
|
657
|
-
|
|
505
|
+
Dao.prototype.set = async function (db, query, body) {
|
|
658
506
|
return await this.setMain(db, query, body);
|
|
659
507
|
};
|
|
660
508
|
|
|
@@ -664,7 +512,7 @@ Drive.prototype.set = async function (db, query, body) {
|
|
|
664
512
|
* @param {object} body 添加项
|
|
665
513
|
* @returns {object} 返回查询结果
|
|
666
514
|
*/
|
|
667
|
-
|
|
515
|
+
Dao.prototype.addMain = async function (db, body) {
|
|
668
516
|
var ret;
|
|
669
517
|
var cg = this.config;
|
|
670
518
|
if (Object.keys(body).length > 0) {
|
|
@@ -687,12 +535,12 @@ Drive.prototype.addMain = async function (db, body) {
|
|
|
687
535
|
}
|
|
688
536
|
var n = await db.add(body);
|
|
689
537
|
if (n < 1) {
|
|
690
|
-
ret =
|
|
538
|
+
ret = getRet().error(500, '添加失败!\n' + db.error.message);
|
|
691
539
|
} else {
|
|
692
|
-
ret =
|
|
540
|
+
ret = getRet().bl(true, '添加成功!');
|
|
693
541
|
}
|
|
694
542
|
} else {
|
|
695
|
-
ret =
|
|
543
|
+
ret = getRet().error(30001, '参数不能为空');
|
|
696
544
|
}
|
|
697
545
|
if (cg.log) {
|
|
698
546
|
this.log('debug', '添加SQL语句', db.sql);
|
|
@@ -707,7 +555,7 @@ Drive.prototype.addMain = async function (db, body) {
|
|
|
707
555
|
* @param {object} body 修改项
|
|
708
556
|
* @returns {object} 返回添加结果
|
|
709
557
|
*/
|
|
710
|
-
|
|
558
|
+
Dao.prototype.add = async function (db, query, body) {
|
|
711
559
|
return await this.addMain(db, body);
|
|
712
560
|
};
|
|
713
561
|
|
|
@@ -717,9 +565,9 @@ Drive.prototype.add = async function (db, query, body) {
|
|
|
717
565
|
* @param {Array} list 添加项列表
|
|
718
566
|
* @returns {object} 返回批量添加结果
|
|
719
567
|
*/
|
|
720
|
-
|
|
568
|
+
Dao.prototype.addListMain = async function (db, list) {
|
|
721
569
|
if (!Array.isArray(list) || list.length === 0) {
|
|
722
|
-
return
|
|
570
|
+
return getRet().error(30001, '参数不能为空');
|
|
723
571
|
}
|
|
724
572
|
var success_num = 0;
|
|
725
573
|
var error_num = 0;
|
|
@@ -735,7 +583,7 @@ Drive.prototype.addListMain = async function (db, list) {
|
|
|
735
583
|
success_num++;
|
|
736
584
|
}
|
|
737
585
|
}
|
|
738
|
-
var done =
|
|
586
|
+
var done = getRet().bl(success_num > 0, success_num > 0 ? '批量添加成功!' : '批量添加失败!');
|
|
739
587
|
Object.assign(done.result, {
|
|
740
588
|
total: list.length,
|
|
741
589
|
success: success_num,
|
|
@@ -752,7 +600,7 @@ Drive.prototype.addListMain = async function (db, list) {
|
|
|
752
600
|
* @param {Array} list 添加项列表
|
|
753
601
|
* @returns {object} 返回批量添加结果
|
|
754
602
|
*/
|
|
755
|
-
|
|
603
|
+
Dao.prototype.addList = async function (db, list) {
|
|
756
604
|
return await this.addListMain(db, list);
|
|
757
605
|
};
|
|
758
606
|
|
|
@@ -762,15 +610,15 @@ Drive.prototype.addList = async function (db, list) {
|
|
|
762
610
|
* @param {object} query 查询条件
|
|
763
611
|
* @returns {object} 返回查询结果
|
|
764
612
|
*/
|
|
765
|
-
|
|
613
|
+
Dao.prototype.delMain = async function (db, query) {
|
|
766
614
|
var ret;
|
|
767
615
|
var { cg, qy } = this.ready(db, query, {});
|
|
768
616
|
var query_str = db.tplQuery(qy, cg.query);
|
|
769
617
|
var bl = await db.delSql(query_str);
|
|
770
618
|
if (bl < 1) {
|
|
771
|
-
ret =
|
|
619
|
+
ret = getRet().error(500, '删除失败!\n' + db.error.message);
|
|
772
620
|
} else {
|
|
773
|
-
ret =
|
|
621
|
+
ret = getRet().bl(true, '删除成功!');
|
|
774
622
|
}
|
|
775
623
|
if (cg.log) {
|
|
776
624
|
this.log('debug', '删除SQL语句', db.sql);
|
|
@@ -785,7 +633,7 @@ Drive.prototype.delMain = async function (db, query) {
|
|
|
785
633
|
* @param {object} body 修改项
|
|
786
634
|
* @returns {object} 返回删除结果
|
|
787
635
|
*/
|
|
788
|
-
|
|
636
|
+
Dao.prototype.del = async function (db, query, body = {}) {
|
|
789
637
|
return await this.delMain(db, { ...query, ...body });
|
|
790
638
|
};
|
|
791
639
|
|
|
@@ -796,18 +644,18 @@ Drive.prototype.del = async function (db, query, body = {}) {
|
|
|
796
644
|
* @param {object} body 修改项
|
|
797
645
|
* @returns {object} 返回修改结果
|
|
798
646
|
*/
|
|
799
|
-
|
|
647
|
+
Dao.prototype.addorsetMain = async function (db, query, body) {
|
|
800
648
|
var ret;
|
|
801
649
|
var { cg, qy } = this.ready(db, query, body);
|
|
802
650
|
if (Object.keys(body).length > 0 && Object.keys(qy).length > 0) {
|
|
803
651
|
var n = await db.addOrSet(qy, body);
|
|
804
652
|
if (n < 1) {
|
|
805
|
-
ret =
|
|
653
|
+
ret = getRet().error(500, '操作失败!\n' + db.error.message);
|
|
806
654
|
} else {
|
|
807
|
-
ret =
|
|
655
|
+
ret = getRet().bl(true, '操作成功!');
|
|
808
656
|
}
|
|
809
657
|
} else {
|
|
810
|
-
ret =
|
|
658
|
+
ret = getRet().error(30001, '参数不能为空');
|
|
811
659
|
}
|
|
812
660
|
if (cg.log) {
|
|
813
661
|
this.log('debug', '添加或修改SQL语句', db.sql);
|
|
@@ -822,7 +670,7 @@ Drive.prototype.addorsetMain = async function (db, query, body) {
|
|
|
822
670
|
* @param {object} body 修改项
|
|
823
671
|
* @returns {object} 返回查询结果
|
|
824
672
|
*/
|
|
825
|
-
|
|
673
|
+
Dao.prototype.addOrSet = async function (db, query, body) {
|
|
826
674
|
return await this.addOrSetMain(db, query, body);
|
|
827
675
|
};
|
|
828
676
|
|
|
@@ -831,7 +679,7 @@ Drive.prototype.addOrSet = async function (db, query, body) {
|
|
|
831
679
|
* @param {string} data_type 数据类型
|
|
832
680
|
* @returns {string} 返回数据类型
|
|
833
681
|
*/
|
|
834
|
-
|
|
682
|
+
Dao.prototype.getType = function (data_type) {
|
|
835
683
|
if (data_type.indexOf('int') !== -1) {
|
|
836
684
|
return 'number';
|
|
837
685
|
} else {
|
|
@@ -845,7 +693,7 @@ Drive.prototype.getType = function (data_type) {
|
|
|
845
693
|
* @param {string} field 要获取的字段
|
|
846
694
|
* @returns {Array} 返回参数信息列表
|
|
847
695
|
*/
|
|
848
|
-
|
|
696
|
+
Dao.prototype.getParam = async function (db, field) {
|
|
849
697
|
var cg = this.config;
|
|
850
698
|
if (cg.params) {
|
|
851
699
|
return cg.params;
|
|
@@ -866,16 +714,9 @@ Drive.prototype.getParam = async function (db, field) {
|
|
|
866
714
|
* @returns {Array} 字段列表
|
|
867
715
|
* @private
|
|
868
716
|
*/
|
|
869
|
-
|
|
717
|
+
Dao.prototype._getFieldsFromCache = function (cg) {
|
|
870
718
|
var lt = [];
|
|
871
|
-
|
|
872
|
-
var get_db_pool = this._getInject('get_db_pool');
|
|
873
|
-
var db_pool = typeof get_db_pool === 'function' ? get_db_pool() : null;
|
|
874
|
-
if (!db_pool) {
|
|
875
|
-
this.log('warn', '未配置 get_db_pool,跳过字段缓存读取');
|
|
876
|
-
return lt;
|
|
877
|
-
}
|
|
878
|
-
var pool = db_pool['sys'];
|
|
719
|
+
var pool = dbAdmin('os');
|
|
879
720
|
if (pool) {
|
|
880
721
|
var dt = pool.get(cg.table);
|
|
881
722
|
if (dt && dt.config) {
|
|
@@ -896,7 +737,7 @@ Drive.prototype._getFieldsFromCache = function (cg) {
|
|
|
896
737
|
* @returns {Array} 字段列表
|
|
897
738
|
* @private
|
|
898
739
|
*/
|
|
899
|
-
|
|
740
|
+
Dao.prototype._getFieldsFromDb = async function (db, cg) {
|
|
900
741
|
var lt = [];
|
|
901
742
|
db.table = cg.table;
|
|
902
743
|
var list = await db.fields();
|
|
@@ -921,7 +762,7 @@ Drive.prototype._getFieldsFromDb = async function (db, cg) {
|
|
|
921
762
|
* @returns {Array} 过滤后的字段列表
|
|
922
763
|
* @private
|
|
923
764
|
*/
|
|
924
|
-
|
|
765
|
+
Dao.prototype._filterFields = function (lt, field, cg) {
|
|
925
766
|
var fields = field || cg.field_default;
|
|
926
767
|
if (fields && fields !== '*') {
|
|
927
768
|
var arr = fields.replace(/`/g, '').split(',');
|
|
@@ -935,7 +776,7 @@ Drive.prototype._filterFields = function (lt, field, cg) {
|
|
|
935
776
|
* @param {object} db 数据库操作类
|
|
936
777
|
* @returns {Array} 格式列表
|
|
937
778
|
*/
|
|
938
|
-
|
|
779
|
+
Dao.prototype.getFormat = async function (db) {
|
|
939
780
|
var dbs = { ...db };
|
|
940
781
|
dbs.size = 0;
|
|
941
782
|
var fmt = this.config.format;
|
|
@@ -966,16 +807,16 @@ Drive.prototype.getFormat = async function (db) {
|
|
|
966
807
|
* @param {string} filename 文件名
|
|
967
808
|
* @returns {object} 返回导入结果
|
|
968
809
|
*/
|
|
969
|
-
|
|
810
|
+
Dao.prototype.importMain = async function (db, filename) {
|
|
970
811
|
var params = await this.getParam(db);
|
|
971
812
|
var format = await this.getFormat(db);
|
|
972
813
|
var file = this._processFilePath(filename);
|
|
973
814
|
if (!file.hasFile(file)) {
|
|
974
|
-
return
|
|
815
|
+
return getRet().error(30001, file + '文件不存在!');
|
|
975
816
|
}
|
|
976
817
|
var jarr = await this._loadImport(file, params, format);
|
|
977
818
|
if (!jarr || !jarr.length) {
|
|
978
|
-
return
|
|
819
|
+
return getRet().error(10000, '要导入的数据不能为空!');
|
|
979
820
|
}
|
|
980
821
|
var result = await this._importToDb(db, jarr);
|
|
981
822
|
return this._buildImport(result);
|
|
@@ -987,7 +828,7 @@ Drive.prototype.importMain = async function (db, filename) {
|
|
|
987
828
|
* @returns {string} 处理后的文件路径
|
|
988
829
|
* @private
|
|
989
830
|
*/
|
|
990
|
-
|
|
831
|
+
Dao.prototype._processFilePath = function (filename) {
|
|
991
832
|
var file = filename;
|
|
992
833
|
var run_path = this._getInject('run_path') || '';
|
|
993
834
|
if (file.indexOf(run_path) !== 0) {
|
|
@@ -1006,10 +847,10 @@ Drive.prototype._processFilePath = function (filename) {
|
|
|
1006
847
|
* @returns {Array} 数据数组
|
|
1007
848
|
* @private
|
|
1008
849
|
*/
|
|
1009
|
-
|
|
1010
|
-
if (
|
|
850
|
+
Dao.prototype._loadImport = async function (file, params, format) {
|
|
851
|
+
if (file.endsWith('.json')) {
|
|
1011
852
|
return file.loadJson(file);
|
|
1012
|
-
} else if (
|
|
853
|
+
} else if (file.endsWith('.xml')) {
|
|
1013
854
|
return file.loadXml(file);
|
|
1014
855
|
} else {
|
|
1015
856
|
const Excel = require('mm_excel');
|
|
@@ -1033,7 +874,7 @@ Drive.prototype._loadImport = async function (file, params, format) {
|
|
|
1033
874
|
* @returns {object} 导入结果
|
|
1034
875
|
* @private
|
|
1035
876
|
*/
|
|
1036
|
-
|
|
877
|
+
Dao.prototype._importToDb = async function (db, jarr) {
|
|
1037
878
|
var list = [];
|
|
1038
879
|
var errors = [];
|
|
1039
880
|
var list_error = [];
|
|
@@ -1073,9 +914,9 @@ Drive.prototype._importToDb = async function (db, jarr) {
|
|
|
1073
914
|
* @returns {object} 返回结果对象
|
|
1074
915
|
* @private
|
|
1075
916
|
*/
|
|
1076
|
-
|
|
917
|
+
Dao.prototype._buildImport = function (result) {
|
|
1077
918
|
var bl = result.list.length === result.total;
|
|
1078
|
-
var body =
|
|
919
|
+
var body = getRet().bl(bl, bl ? '导入成功!' : '导入失败!');
|
|
1079
920
|
body.result.list = result.list;
|
|
1080
921
|
if (result.errors.length) {
|
|
1081
922
|
body.result.list_error = result.list_error;
|
|
@@ -1091,10 +932,10 @@ Drive.prototype._buildImport = function (result) {
|
|
|
1091
932
|
* @param {object} body 导入设置
|
|
1092
933
|
* @returns {object} 返回执行结果
|
|
1093
934
|
*/
|
|
1094
|
-
|
|
935
|
+
Dao.prototype.import = async function (db, query, body) {
|
|
1095
936
|
var params = { ...query, ...body };
|
|
1096
937
|
if (!params.file) {
|
|
1097
|
-
return
|
|
938
|
+
return getRet().error(60000, '文件名(file)参数不能为空');
|
|
1098
939
|
}
|
|
1099
940
|
return await this.importMain(db, params.file);
|
|
1100
941
|
};
|
|
@@ -1109,10 +950,10 @@ Drive.prototype.import = async function (db, query, body) {
|
|
|
1109
950
|
* @property {string} body.path 文件路径 例如: /static/download, 可不填写
|
|
1110
951
|
* @returns {object} 返回执行结果
|
|
1111
952
|
*/
|
|
1112
|
-
|
|
953
|
+
Dao.prototype.exportMain = async function (db, query, body) {
|
|
1113
954
|
var by = await this.getMain(db, query);
|
|
1114
955
|
if (db.error) {
|
|
1115
|
-
return
|
|
956
|
+
return getRet().error(10000, db.error.message);
|
|
1116
957
|
}
|
|
1117
958
|
var config = this._prepareExportConfig(query, body);
|
|
1118
959
|
var params = await this.getParam(db, config.fields);
|
|
@@ -1133,7 +974,7 @@ Drive.prototype.exportMain = async function (db, query, body) {
|
|
|
1133
974
|
* @returns {object} 导出配置
|
|
1134
975
|
* @private
|
|
1135
976
|
*/
|
|
1136
|
-
|
|
977
|
+
Dao.prototype._prepareExportConfig = function (query, body) {
|
|
1137
978
|
var path = body.path;
|
|
1138
979
|
var file = body.file;
|
|
1139
980
|
var fields = body.fields;
|
|
@@ -1158,7 +999,7 @@ Drive.prototype._prepareExportConfig = function (query, body) {
|
|
|
1158
999
|
* @returns {string} 导出路径
|
|
1159
1000
|
* @private
|
|
1160
1001
|
*/
|
|
1161
|
-
|
|
1002
|
+
Dao.prototype._getPath = function () {
|
|
1162
1003
|
return (
|
|
1163
1004
|
this._getInject('user_path') ||
|
|
1164
1005
|
this._getInject('static_path') ||
|
|
@@ -1175,7 +1016,7 @@ Drive.prototype._getPath = function () {
|
|
|
1175
1016
|
* @returns {string} 保存后的文件路径
|
|
1176
1017
|
* @private
|
|
1177
1018
|
*/
|
|
1178
|
-
|
|
1019
|
+
Dao.prototype._saveExportFile = async function (file, params, format, list) {
|
|
1179
1020
|
var export_path = this._getPath();
|
|
1180
1021
|
var save_file = file.fullname(file, export_path);
|
|
1181
1022
|
file.addDir(save_file);
|
|
@@ -1199,8 +1040,8 @@ Drive.prototype._saveExportFile = async function (file, params, format, list) {
|
|
|
1199
1040
|
* @returns {object} 导出结果
|
|
1200
1041
|
* @private
|
|
1201
1042
|
*/
|
|
1202
|
-
|
|
1203
|
-
var body =
|
|
1043
|
+
Dao.prototype._buildExport = function (file, name) {
|
|
1044
|
+
var body = getRet().bl(!!file, file ? '导出成功!' : '导出失败!');
|
|
1204
1045
|
body.result.file = file;
|
|
1205
1046
|
body.result.url = this.url_path + name;
|
|
1206
1047
|
return body;
|
|
@@ -1213,7 +1054,7 @@ Drive.prototype._buildExport = function (file, name) {
|
|
|
1213
1054
|
* @param {object} body 修改项
|
|
1214
1055
|
* @returns {object} 返回执行结果
|
|
1215
1056
|
*/
|
|
1216
|
-
|
|
1057
|
+
Dao.prototype.export = async function (db, query, body) {
|
|
1217
1058
|
return await this.exportMain(db, query, body);
|
|
1218
1059
|
};
|
|
1219
1060
|
|
|
@@ -1223,18 +1064,23 @@ Drive.prototype.export = async function (db, query, body) {
|
|
|
1223
1064
|
* @param {object} params 查询参数
|
|
1224
1065
|
* @returns {object} 返回执行结果
|
|
1225
1066
|
*/
|
|
1226
|
-
|
|
1067
|
+
Dao.prototype.delRepeatMain = async function (db, params) {
|
|
1227
1068
|
var pm = { ...params };
|
|
1228
1069
|
var msg = '';
|
|
1229
1070
|
var cg = this.config.del_repeat;
|
|
1230
1071
|
var order_by = pm.orderby || cg.orderby;
|
|
1231
1072
|
delete pm.orderby;
|
|
1073
|
+
var group_by_val = pm.groupby || cg.groupby;
|
|
1232
1074
|
var group_by =
|
|
1233
|
-
|
|
1075
|
+
(typeof group_by_val === 'string' && string.validate(group_by_val, 'username') ? group_by_val : '') ||
|
|
1076
|
+
cg.groupby ||
|
|
1077
|
+
'';
|
|
1234
1078
|
delete pm.groupby;
|
|
1235
1079
|
var f = db.config.filter;
|
|
1236
1080
|
// 设置查询字段
|
|
1237
|
-
var field =
|
|
1081
|
+
var field =
|
|
1082
|
+
(typeof pm[f.field] === 'string' && string.validate(pm[f.field], 'username') ? pm[f.field] : '') ||
|
|
1083
|
+
group_by;
|
|
1238
1084
|
delete pm[f.field];
|
|
1239
1085
|
db.field = field;
|
|
1240
1086
|
var sql = db
|
|
@@ -1261,7 +1107,7 @@ Drive.prototype.delRepeatMain = async function (db, params) {
|
|
|
1261
1107
|
} else {
|
|
1262
1108
|
msg = '没有重复项。';
|
|
1263
1109
|
}
|
|
1264
|
-
return
|
|
1110
|
+
return getRet().bl(!msg, msg ? '去重失败!原因:' + msg : '去重成功!');
|
|
1265
1111
|
};
|
|
1266
1112
|
|
|
1267
1113
|
/**
|
|
@@ -1271,7 +1117,7 @@ Drive.prototype.delRepeatMain = async function (db, params) {
|
|
|
1271
1117
|
* @param {object} body 正文参数
|
|
1272
1118
|
* @returns {object} 返回执行结果
|
|
1273
1119
|
*/
|
|
1274
|
-
|
|
1120
|
+
Dao.prototype.delRepeat = async function (db, query, body) {
|
|
1275
1121
|
var pm = { ...query, ...body };
|
|
1276
1122
|
return await this.delRepeatMain(db, pm);
|
|
1277
1123
|
};
|
|
@@ -1282,7 +1128,7 @@ Drive.prototype.delRepeat = async function (db, query, body) {
|
|
|
1282
1128
|
* @param {object} db 数据管理器
|
|
1283
1129
|
* @returns {object} 返回执行结果
|
|
1284
1130
|
*/
|
|
1285
|
-
|
|
1131
|
+
Dao.prototype.main = async function (params, db) {
|
|
1286
1132
|
var { query, body } = params;
|
|
1287
1133
|
|
|
1288
1134
|
var cg = this.config;
|
|
@@ -1292,7 +1138,7 @@ Drive.prototype.main = async function (params, db) {
|
|
|
1292
1138
|
method = 'get';
|
|
1293
1139
|
}
|
|
1294
1140
|
if (!string.has(cg.method, '*' + method + '*')) {
|
|
1295
|
-
return
|
|
1141
|
+
return getRet().error(50001, '不支持的操作方式');
|
|
1296
1142
|
}
|
|
1297
1143
|
method = this._getMethodName(method);
|
|
1298
1144
|
var qy = { ...query };
|
|
@@ -1303,17 +1149,17 @@ Drive.prototype.main = async function (params, db) {
|
|
|
1303
1149
|
// 过滤查询参数
|
|
1304
1150
|
var f = cg.filter;
|
|
1305
1151
|
var table = query[f.table];
|
|
1306
|
-
var safe_table =
|
|
1152
|
+
var safe_table = typeof table === 'string' && string.validate(table, 'username') ? table : '';
|
|
1307
1153
|
|
|
1308
1154
|
// 设置操作的数据表
|
|
1309
1155
|
if (string.has(cg.table, '*{0}*')) {
|
|
1310
1156
|
if (table) {
|
|
1311
1157
|
if (!safe_table) {
|
|
1312
|
-
return
|
|
1158
|
+
return getRet().error(30001, '表名包含无效字符');
|
|
1313
1159
|
}
|
|
1314
1160
|
db.table = cg.table.replace('{0}', safe_table);
|
|
1315
1161
|
} else {
|
|
1316
|
-
return
|
|
1162
|
+
return getRet().error(30001, '表名不能为空');
|
|
1317
1163
|
}
|
|
1318
1164
|
} else {
|
|
1319
1165
|
db.table = cg.table + '';
|
|
@@ -1321,7 +1167,7 @@ Drive.prototype.main = async function (params, db) {
|
|
|
1321
1167
|
|
|
1322
1168
|
return await this[method](db, qy, { ...body });
|
|
1323
1169
|
} else {
|
|
1324
|
-
return
|
|
1170
|
+
return getRet().error(50001, '不支持的操作方式');
|
|
1325
1171
|
}
|
|
1326
1172
|
};
|
|
1327
1173
|
|
|
@@ -1331,7 +1177,7 @@ Drive.prototype.main = async function (params, db) {
|
|
|
1331
1177
|
* @returns {string} 方法名
|
|
1332
1178
|
* @private
|
|
1333
1179
|
*/
|
|
1334
|
-
|
|
1180
|
+
Dao.prototype._getMethodName = function (method) {
|
|
1335
1181
|
if (!method) {
|
|
1336
1182
|
return '';
|
|
1337
1183
|
}
|
|
@@ -1354,7 +1200,7 @@ Drive.prototype._getMethodName = function (method) {
|
|
|
1354
1200
|
* @param {object} param 查询条件
|
|
1355
1201
|
* @returns {object} 返回执行结果
|
|
1356
1202
|
*/
|
|
1357
|
-
|
|
1203
|
+
Dao.prototype.sumMain = async function (db, param) {
|
|
1358
1204
|
var pm = { ...param };
|
|
1359
1205
|
var ret;
|
|
1360
1206
|
var orderby = pm.orderby || '';
|
|
@@ -1367,13 +1213,13 @@ Drive.prototype.sumMain = async function (db, param) {
|
|
|
1367
1213
|
var query_str = this.toWhere(db, pm, 'get_list');
|
|
1368
1214
|
|
|
1369
1215
|
if (!groupby || !field) {
|
|
1370
|
-
ret =
|
|
1216
|
+
ret = getRet().error(30000, '参数groupby、field是必须的,且值不能为空!');
|
|
1371
1217
|
} else {
|
|
1372
1218
|
var list = await db.groupSumSql(query_str, groupby, field, orderby);
|
|
1373
1219
|
if (!list.length && db.error) {
|
|
1374
|
-
ret =
|
|
1220
|
+
ret = getRet().body(db.error);
|
|
1375
1221
|
} else {
|
|
1376
|
-
ret =
|
|
1222
|
+
ret = getRet().list(list);
|
|
1377
1223
|
}
|
|
1378
1224
|
}
|
|
1379
1225
|
return ret;
|
|
@@ -1386,7 +1232,7 @@ Drive.prototype.sumMain = async function (db, param) {
|
|
|
1386
1232
|
* @param {object} body 正文参数
|
|
1387
1233
|
* @returns {object} 返回执行结果
|
|
1388
1234
|
*/
|
|
1389
|
-
|
|
1235
|
+
Dao.prototype.sum = async function (db, query, body) {
|
|
1390
1236
|
var pm = { ...query, ...body };
|
|
1391
1237
|
return await this.sumMain(db, pm);
|
|
1392
1238
|
};
|
|
@@ -1397,7 +1243,7 @@ Drive.prototype.sum = async function (db, query, body) {
|
|
|
1397
1243
|
* @param {object} param 查询条件
|
|
1398
1244
|
* @returns {object} 返回执行结果
|
|
1399
1245
|
*/
|
|
1400
|
-
|
|
1246
|
+
Dao.prototype.avgMain = async function (db, param) {
|
|
1401
1247
|
var pm = { ...param };
|
|
1402
1248
|
var ret;
|
|
1403
1249
|
var orderby = pm.orderby || '';
|
|
@@ -1410,13 +1256,13 @@ Drive.prototype.avgMain = async function (db, param) {
|
|
|
1410
1256
|
var query_str = this.toWhere(db, pm, 'get_list');
|
|
1411
1257
|
|
|
1412
1258
|
if (!groupby || !field) {
|
|
1413
|
-
ret =
|
|
1259
|
+
ret = getRet().error(30000, '参数groupby、field是必须的,且值不能为空!');
|
|
1414
1260
|
} else {
|
|
1415
1261
|
var list = await db.groupAvgSql(query_str, groupby, field, orderby);
|
|
1416
1262
|
if (!list.length && db.error) {
|
|
1417
|
-
ret =
|
|
1263
|
+
ret = getRet().body(db.error);
|
|
1418
1264
|
} else {
|
|
1419
|
-
ret =
|
|
1265
|
+
ret = getRet().list(list);
|
|
1420
1266
|
}
|
|
1421
1267
|
}
|
|
1422
1268
|
return ret;
|
|
@@ -1429,7 +1275,7 @@ Drive.prototype.avgMain = async function (db, param) {
|
|
|
1429
1275
|
* @param {object} body 正文参数
|
|
1430
1276
|
* @returns {object} 返回执行结果
|
|
1431
1277
|
*/
|
|
1432
|
-
|
|
1278
|
+
Dao.prototype.avg = async function (db, query, body) {
|
|
1433
1279
|
var pm = { ...query, ...body };
|
|
1434
1280
|
return await this.avgMain(db, pm);
|
|
1435
1281
|
};
|
|
@@ -1440,7 +1286,7 @@ Drive.prototype.avg = async function (db, query, body) {
|
|
|
1440
1286
|
* @param {object} param 查询条件
|
|
1441
1287
|
* @returns {object} 返回执行结果
|
|
1442
1288
|
*/
|
|
1443
|
-
|
|
1289
|
+
Dao.prototype.countMain = async function (db, param) {
|
|
1444
1290
|
var pm = { ...param };
|
|
1445
1291
|
var ret;
|
|
1446
1292
|
var orderby = pm.orderby || '';
|
|
@@ -1453,13 +1299,13 @@ Drive.prototype.countMain = async function (db, param) {
|
|
|
1453
1299
|
var query_str = this.toWhere(db, pm, 'get_list');
|
|
1454
1300
|
|
|
1455
1301
|
if (!groupby || !field) {
|
|
1456
|
-
ret =
|
|
1302
|
+
ret = getRet().error(30000, '参数groupby、field是必须的,且值不能为空!');
|
|
1457
1303
|
} else {
|
|
1458
1304
|
var list = await db.groupCountSql(query_str, groupby, field, orderby);
|
|
1459
1305
|
if (!list.length && db.error) {
|
|
1460
|
-
ret =
|
|
1306
|
+
ret = getRet().body(db.error);
|
|
1461
1307
|
} else {
|
|
1462
|
-
ret =
|
|
1308
|
+
ret = getRet().list(list);
|
|
1463
1309
|
}
|
|
1464
1310
|
}
|
|
1465
1311
|
return ret;
|
|
@@ -1472,7 +1318,7 @@ Drive.prototype.countMain = async function (db, param) {
|
|
|
1472
1318
|
* @param {object} body 正文参数
|
|
1473
1319
|
* @returns {object} 返回执行结果
|
|
1474
1320
|
*/
|
|
1475
|
-
|
|
1321
|
+
Dao.prototype.count = async function (db, query, body) {
|
|
1476
1322
|
var pm = { ...query, ...body };
|
|
1477
1323
|
return await this.countMain(db, pm);
|
|
1478
1324
|
};
|
|
@@ -1482,7 +1328,7 @@ Drive.prototype.count = async function (db, query, body) {
|
|
|
1482
1328
|
* @param {string} type 模型类型
|
|
1483
1329
|
* @returns {object} 返回获取到的模型
|
|
1484
1330
|
*/
|
|
1485
|
-
|
|
1331
|
+
Dao.prototype.getModel = function (type) {
|
|
1486
1332
|
let model = { ...this.config };
|
|
1487
1333
|
let dir = this.config.dir || '';
|
|
1488
1334
|
let l = path.sep;
|
|
@@ -1494,4 +1340,4 @@ Drive.prototype.getModel = function (type) {
|
|
|
1494
1340
|
model.name = model.name || app_name + '_' + name;
|
|
1495
1341
|
return model;
|
|
1496
1342
|
};
|
|
1497
|
-
module.exports =
|
|
1343
|
+
module.exports = Dao;
|
package/lib/manager.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
|
-
const Manager = require(
|
|
3
|
-
const
|
|
4
|
-
const {
|
|
2
|
+
const Manager = require('mm_machine').Manager;
|
|
3
|
+
const Dao = require("./dao");
|
|
4
|
+
const { getSql } = require("mm_sql");
|
|
5
5
|
const { array } = require("mm_helper");
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -9,7 +9,7 @@ const { array } = require("mm_helper");
|
|
|
9
9
|
* @augments {Manager}
|
|
10
10
|
* @class
|
|
11
11
|
*/
|
|
12
|
-
class
|
|
12
|
+
class DaoManager extends Manager {
|
|
13
13
|
/**
|
|
14
14
|
* 配置参数
|
|
15
15
|
* @type {object}
|
|
@@ -39,11 +39,6 @@ class SqlManager extends Manager {
|
|
|
39
39
|
user_id: "user_id",
|
|
40
40
|
token: "x-auth-token",
|
|
41
41
|
},
|
|
42
|
-
/**
|
|
43
|
-
* 数据库池获取函数(可选注入,返回数据库池注册表;未配置则驱动跳过字段缓存)
|
|
44
|
-
* @type {Function|null}
|
|
45
|
-
*/
|
|
46
|
-
get_db_pool: null,
|
|
47
42
|
/**
|
|
48
43
|
* 用户路径(导出目录优先,替代原全局 config 的 user_path)
|
|
49
44
|
* @type {string}
|
|
@@ -67,11 +62,9 @@ class SqlManager extends Manager {
|
|
|
67
62
|
* @param {object} parent 父级模块
|
|
68
63
|
*/
|
|
69
64
|
constructor(config, parent) {
|
|
70
|
-
super({ ...
|
|
71
|
-
// 插件注册表(方案B:手动注册,替代原全局插件池)
|
|
72
|
-
this.plugins = {};
|
|
65
|
+
super({ ...DaoManager.config, ...config }, parent);
|
|
73
66
|
// 兼容 Sql 实例(惰性创建,供 db()/load() 等价入口委托)
|
|
74
|
-
this._sql =
|
|
67
|
+
this._sql = getSql();
|
|
75
68
|
}
|
|
76
69
|
}
|
|
77
70
|
|
|
@@ -79,18 +72,44 @@ class SqlManager extends Manager {
|
|
|
79
72
|
* sql驱动类
|
|
80
73
|
* @type {Drive}
|
|
81
74
|
*/
|
|
82
|
-
|
|
75
|
+
DaoManager.prototype.Drive = Dao;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* 初始化桥接(生命周期汇聚点:init() 与 do('init') 均调用,触发 onInit)
|
|
79
|
+
* @returns {Promise<void>} 初始化完成
|
|
80
|
+
* @private
|
|
81
|
+
*/
|
|
82
|
+
DaoManager.prototype._init = async function () {
|
|
83
|
+
await this.onInit();
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 启动桥接(生命周期汇聚点,触发 onStart)
|
|
88
|
+
* @returns {Promise<void>} 启动完成
|
|
89
|
+
* @private
|
|
90
|
+
*/
|
|
91
|
+
DaoManager.prototype._start = async function () {
|
|
92
|
+
await this.onStart();
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 停止桥接(生命周期汇聚点,触发 onStop)
|
|
97
|
+
* @returns {Promise<void>} 停止完成
|
|
98
|
+
* @private
|
|
99
|
+
*/
|
|
100
|
+
DaoManager.prototype._stop = async function () {
|
|
101
|
+
await this.onStop();
|
|
102
|
+
};
|
|
83
103
|
|
|
84
104
|
/**
|
|
85
105
|
* 注册一个 sql 驱动(方案B:手动注册,不扫描目录)
|
|
86
106
|
* @param {object} config 驱动配置(必须包含 name)
|
|
87
107
|
* @returns {object} 驱动实例
|
|
88
108
|
*/
|
|
89
|
-
|
|
90
|
-
var drive = new Drive(
|
|
109
|
+
DaoManager.prototype.add = function (config) {
|
|
110
|
+
var drive = new this.Drive(
|
|
91
111
|
{
|
|
92
112
|
dict: this.config.dict,
|
|
93
|
-
get_db_pool: this.config.get_db_pool,
|
|
94
113
|
user_path: this.config.user_path,
|
|
95
114
|
static_path: this.config.static_path,
|
|
96
115
|
run_path: this.config.run_path,
|
|
@@ -107,7 +126,7 @@ SqlManager.prototype.add = function (config) {
|
|
|
107
126
|
* @param {string} name 驱动名称
|
|
108
127
|
* @returns {Promise<boolean>} 是否删除成功
|
|
109
128
|
*/
|
|
110
|
-
|
|
129
|
+
DaoManager.prototype.del = async function (name) {
|
|
111
130
|
var drive = this.get(name);
|
|
112
131
|
if (drive) {
|
|
113
132
|
await drive.stop();
|
|
@@ -121,7 +140,7 @@ SqlManager.prototype.del = async function (name) {
|
|
|
121
140
|
* @param {string} name 驱动名称
|
|
122
141
|
* @returns {Promise<boolean>} 是否执行成功
|
|
123
142
|
*/
|
|
124
|
-
|
|
143
|
+
DaoManager.prototype.reload = async function (name) {
|
|
125
144
|
var drive = this.get(name);
|
|
126
145
|
if (!drive) {
|
|
127
146
|
this.log("warn", "驱动不存在,无法重启", name);
|
|
@@ -139,26 +158,13 @@ SqlManager.prototype.reload = async function (name) {
|
|
|
139
158
|
};
|
|
140
159
|
|
|
141
160
|
/**
|
|
142
|
-
*
|
|
143
|
-
* @param {string} name 插件作用域名称(app 名)
|
|
144
|
-
* @param {object} obj 插件集合对象(需含 get 方法)
|
|
145
|
-
* @returns {object} 当前管理器实例
|
|
146
|
-
*/
|
|
147
|
-
SqlManager.prototype.usePlugin = function (name, obj) {
|
|
148
|
-
this.plugins[name] = obj;
|
|
149
|
-
return this;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* 初始化驱动实例(仅未初始化时执行生命周期 init,重复调用安全)
|
|
161
|
+
* 初始化驱动实例(执行生命周期 init)
|
|
154
162
|
* @param {object} drive 驱动实例
|
|
155
163
|
* @returns {Promise<void>} 初始化完成
|
|
156
164
|
* @private
|
|
157
165
|
*/
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
await drive.init();
|
|
161
|
-
}
|
|
166
|
+
DaoManager.prototype._initDrive = async function (drive) {
|
|
167
|
+
await drive.init();
|
|
162
168
|
};
|
|
163
169
|
|
|
164
170
|
/**
|
|
@@ -166,7 +172,7 @@ SqlManager.prototype._initDrive = async function (drive) {
|
|
|
166
172
|
* @returns {Array} 驱动配置数组
|
|
167
173
|
* @private
|
|
168
174
|
*/
|
|
169
|
-
|
|
175
|
+
DaoManager.prototype._getInfos = function () {
|
|
170
176
|
return this.values().map((d) => d.config);
|
|
171
177
|
};
|
|
172
178
|
|
|
@@ -174,8 +180,8 @@ SqlManager.prototype._getInfos = function () {
|
|
|
174
180
|
* 排序(返回按名称升序的驱动配置列表)
|
|
175
181
|
* @returns {Array} 排序后的配置列表
|
|
176
182
|
*/
|
|
177
|
-
|
|
178
|
-
var infos = this.
|
|
183
|
+
DaoManager.prototype.sort = function () {
|
|
184
|
+
var infos = this.configs;
|
|
179
185
|
return array.sortBy(infos, "asc", "name");
|
|
180
186
|
};
|
|
181
187
|
|
|
@@ -187,7 +193,7 @@ SqlManager.prototype.sort = function () {
|
|
|
187
193
|
* @param {object} db 数据库管理器 (object) 只支持可用sql语句的数据库
|
|
188
194
|
* @returns {object} 执行结果
|
|
189
195
|
*/
|
|
190
|
-
|
|
196
|
+
DaoManager.prototype.run = async function (name, query, body, db) {
|
|
191
197
|
var obj = this.get(name);
|
|
192
198
|
if (obj) {
|
|
193
199
|
return await obj.run(query, body, db);
|
|
@@ -200,7 +206,7 @@ SqlManager.prototype.run = async function (name, query, body, db) {
|
|
|
200
206
|
* @returns {Sql} 兼容 Sql 实例
|
|
201
207
|
* @private
|
|
202
208
|
*/
|
|
203
|
-
|
|
209
|
+
DaoManager.prototype._getSql = function () {
|
|
204
210
|
if (!this._sql) {
|
|
205
211
|
var SERVER = this.getServer();
|
|
206
212
|
var server_config = (SERVER && SERVER.config) || {};
|
|
@@ -223,7 +229,7 @@ SqlManager.prototype._getSql = function () {
|
|
|
223
229
|
* 获取数据库管理器(等价入口,委托内部 Sql 实例)
|
|
224
230
|
* @returns {object} 数据库管理器实例
|
|
225
231
|
*/
|
|
226
|
-
|
|
232
|
+
DaoManager.prototype.db = function () {
|
|
227
233
|
return this._getSql().db();
|
|
228
234
|
};
|
|
229
235
|
|
|
@@ -232,8 +238,8 @@ SqlManager.prototype.db = function () {
|
|
|
232
238
|
* @param {string} file SQL 文件路径
|
|
233
239
|
* @returns {Promise<object>} 执行结果统计对象
|
|
234
240
|
*/
|
|
235
|
-
|
|
241
|
+
DaoManager.prototype.load = function (file) {
|
|
236
242
|
return this._getSql().load(file);
|
|
237
243
|
};
|
|
238
244
|
|
|
239
|
-
module.exports =
|
|
245
|
+
module.exports = DaoManager;
|
package/package.json
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "mm_dao",
|
|
3
|
+
"version": "1.8.2",
|
|
4
|
+
"description": "一个通用的SQL帮助类,支持通过切换db_type实现对不同数据库的操作,包括MySQL和SQLite等;另提供 manager.js/drive.js 的SQL模板管理器(融合自 mm_os com/sql,基于 mm_corejs,内置管理器池,无全局/原型扩展依赖)",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node tests/test.js",
|
|
8
|
+
"test": "node tests/test.js",
|
|
9
|
+
"lint": "eslint . --config eslint.config.js",
|
|
10
|
+
"lint:fix": "eslint . --config eslint.config.js --fix",
|
|
11
|
+
"lint:check": "eslint . --config eslint.config.js --max-warnings 0"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://gitee.com/qiuwenwu91/mm_dao.git"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"mm_mod",
|
|
19
|
+
"mm_infra",
|
|
20
|
+
"mm_runtime",
|
|
21
|
+
"sql",
|
|
22
|
+
"mysql",
|
|
23
|
+
"sql server",
|
|
24
|
+
"sqlite",
|
|
25
|
+
"database",
|
|
26
|
+
"async",
|
|
27
|
+
"await",
|
|
28
|
+
"promise",
|
|
29
|
+
"add",
|
|
30
|
+
"del",
|
|
31
|
+
"set",
|
|
32
|
+
"get",
|
|
33
|
+
"query",
|
|
34
|
+
"run",
|
|
35
|
+
"exec",
|
|
36
|
+
"orm",
|
|
37
|
+
"多数据库",
|
|
38
|
+
"database-adapter"
|
|
39
|
+
],
|
|
40
|
+
"layer": "infra",
|
|
41
|
+
"group": "repo",
|
|
42
|
+
"author": "邱文武",
|
|
43
|
+
"license": "ISC",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://gitee.com/qiuwenwu91/mm_dao/issues"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://gitee.com/qiuwenwu91/mm_dao#readme",
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=12.0.0"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"mm_corejs": "^1.1.4",
|
|
53
|
+
"mm_dbs": "^1.0.1",
|
|
54
|
+
"mm_excel": "^1.2.4",
|
|
55
|
+
"mm_helper": "^1.0.0",
|
|
56
|
+
"mm_machine": "^3.5.4",
|
|
57
|
+
"mm_ret": "^1.4.8",
|
|
58
|
+
"mm_sql": "^1.8.0"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"eslint": "^10.9.1",
|
|
62
|
+
"eslint-plugin-jsdoc": "^64.2.1",
|
|
63
|
+
"mm_eslint": "^1.7.7"
|
|
64
|
+
}
|
|
65
|
+
}
|