dborm-mysql 2.1.4 → 2.2.1

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.
@@ -0,0 +1,536 @@
1
+ /**
2
+ * Created by zhangdianpeng on 2017/8/8.
3
+ */
4
+
5
+ const co = require('co');
6
+
7
+ let db2ramFieldMap = require('./config/db2ramFieldMap.json');
8
+ let textDbFieldsMap = require('./config/textDbFields.json');
9
+ let dbConfig = {
10
+ "connectionLimit": 10,
11
+ "database": "test",
12
+ "host": "127.0.0.1",
13
+ "user": "*****",
14
+ "port": 3360,
15
+ "password": "******",
16
+ "multipleStatements": true
17
+ };
18
+
19
+ let dbORM = require('./index')({
20
+ log: true,
21
+ dbConfig,
22
+ db2ramFieldMap,
23
+ textDbFieldsMap,
24
+ options: {
25
+ dbCode: 734,
26
+ noConvertDbCodes: [735]
27
+ }
28
+ });
29
+
30
+ // process.MYSQL_READ_ONLY = true;
31
+
32
+ const TableName = 'sample';
33
+ let sampleDao = dbORM(TableName);
34
+ let {dbUtil, db} = sampleDao;
35
+
36
+
37
+ //istanbul cover node_modules/mocha/bin/_mocha src/app/server/test/dao
38
+ let should = require('chai').should();
39
+ let expect = require('chai').expect;
40
+
41
+ let id0, id1;
42
+
43
+ let sample = {
44
+ projectId: 1,
45
+ name: 'sampleTest',
46
+ json: {
47
+ a: 1,
48
+ b: 2
49
+ }
50
+ };
51
+
52
+ let wrapAdd = co.wrap(function*(){
53
+ let dbWrapFun = function(sample, conn) {
54
+ return sampleDao.add(sample, conn).then(insertId => {throw {insertId, code: 736}});
55
+ };
56
+
57
+ for(let i = 0; i < 10; i++){
58
+ let newSample = {
59
+ projectId: 1,
60
+ name: i
61
+ };
62
+ try{
63
+ yield db.wrapTransaction(dbWrapFun, 1)(newSample);
64
+ }catch(err){
65
+ console.log('err:', err);
66
+ }
67
+ }
68
+ return 'ok';
69
+ });
70
+
71
+ describe('sampleDao', function(){
72
+
73
+
74
+ //add接口
75
+ describe('db.wrapTranscation', function(){
76
+ it('事务处理', function (){
77
+ return wrapAdd().then(res => {
78
+ res.should.to.be.a('string');
79
+ });
80
+ });
81
+ });
82
+
83
+ //add接口
84
+ describe('add', function(){
85
+ it('插入单条数据,返回插入的id', function (){
86
+ return sampleDao.add(sample).then(insertId => {
87
+ insertId.should.to.be.a('number');
88
+ insertId.should.to.be.least(0);
89
+ id0 = insertId;
90
+ console.log('id0:', id0);
91
+ })
92
+ });
93
+ it('插入数据为空,抛出500异常', function (){
94
+ return sampleDao.add({}).catch(err => {
95
+ console.log('500.empty.message:', err);
96
+ err.code.should.to.equal(734);
97
+ })
98
+ });
99
+ it('插入带id的数据', function (){
100
+ return sampleDao.add({id: 1, projectId: 2}).then(insertId => {
101
+ insertId.should.to.be.a('number');
102
+ insertId.should.to.be.least(0);
103
+ })
104
+ });
105
+ });
106
+
107
+ //createBulk接口
108
+ describe('createBulk 批量插入数据,返回的插入id只有一个', function(){
109
+ it('return a object', function (){
110
+ return sampleDao.createBulk([sample, sample]).then(res => {
111
+ id1 = res.insertId;
112
+ console.log('id1:', id1);
113
+ res.should.to.be.a('object');
114
+ })
115
+ });
116
+ it('有某些数据为空时,抛出异常500', function (){
117
+ return sampleDao.createBulk([{}, sample, {}]).catch(err => {
118
+ console.log('message:', err.message);
119
+ err.code.should.to.equal(734);
120
+ })
121
+ });
122
+ });
123
+
124
+ //get接口
125
+ describe('get', function(){
126
+ it('如果指定id不存在,返回undefined', function (){
127
+ return sampleDao.get(100000).then(res => {
128
+ expect(res).to.be.an('undefined');
129
+ })
130
+ });
131
+ it('返回指定id的sample', function (){
132
+ return sampleDao.get(id0).then(res => {
133
+ res.should.to.be.an('object');
134
+ })
135
+ });
136
+ });
137
+
138
+ //pageQuery接口
139
+ describe('pageQuery', function(){
140
+ it('分页查询返回 count and list', function (){
141
+ return sampleDao.pageQuery({
142
+ initSql: 'select project_id as projectId, name from sample where id = ?',
143
+ initParams: [1],
144
+ offset: 0,
145
+ limit: 20,
146
+ sort: ['name:2'],
147
+ keyword: {
148
+ name: 'xx'
149
+ },
150
+ initSessionSql: 'select 1'
151
+ }).then(res => {
152
+ expect(res.count).to.be.a('number');
153
+ expect(res.list).to.be.an('array');
154
+ })
155
+ });
156
+
157
+ it('分页查询返回 only count', function (){
158
+ return sampleDao.pageQuery({
159
+ initSql: 'select project_id as projectId, name from sample where id = ?',
160
+ initParams: [1],
161
+ offset: 0,
162
+ limit: 20,
163
+ sort: ['name:2'],
164
+ returnFields: ['count'],
165
+ keyword: {
166
+ name: 'xx'
167
+ }
168
+ }).then(res => {
169
+ expect(res.count).to.be.a('number');
170
+ expect(res.list).to.be.an('null');
171
+ })
172
+ });
173
+
174
+ it('分页查询返回 only list', function (){
175
+ return sampleDao.pageQuery({
176
+ initSql: 'select project_id as projectId, name from sample where id = ?',
177
+ initParams: [1],
178
+ offset: 0,
179
+ limit: 20,
180
+ sort: ['name:2'],
181
+ returnFields: ['list'],
182
+ keyword: {
183
+ name: 'xx'
184
+ }
185
+ }).then(res => {
186
+ expect(res.count).to.be.an('null');
187
+ expect(res.list).to.be.an('array');
188
+ })
189
+ });
190
+ });
191
+
192
+ //getList接口
193
+ describe('getList', function(){
194
+ let query = {
195
+ selectFields: 'projectId',
196
+ projectId: 1,
197
+ keyword: {
198
+ name: 's\amp_l%e'
199
+ },
200
+ initSessionSql: 'select 1'
201
+ };
202
+ it('return dashboards', function (){
203
+ return sampleDao.getList(Object.assign({}, {inFields: {
204
+ id: [id0, id1]
205
+ }})).then(res =>{
206
+ res.should.to.be.instanceOf(Array);
207
+ })
208
+ });
209
+ let queryWithSortAsc = Object.assign({}, query, {
210
+ inFields: {
211
+ id: [],
212
+ },
213
+ sort: "name:1"
214
+ });
215
+ it('按照指定字段升序', function (){
216
+ return sampleDao.getList(queryWithSortAsc).then(res =>{
217
+ res.should.to.be.instanceOf(Array);
218
+ })
219
+ });
220
+ let queryWithSortDec = Object.assign({}, query, {
221
+ sort: "name:2"
222
+ });
223
+ it('按照指定字段降序', function (){
224
+ return sampleDao.getList(queryWithSortDec).then(res =>{
225
+ res.should.to.be.instanceOf(Array);
226
+ })
227
+ });
228
+
229
+ let queryWithSortArray = Object.assign({}, query, {
230
+ sort: ["name:2", "id:1", "projectId:2"]
231
+ });
232
+ it('queryWithSortArrayTest', function (){
233
+ return sampleDao.getList(queryWithSortArray).then(res =>{
234
+ res.should.to.be.instanceOf(Array);
235
+ })
236
+ });
237
+
238
+ let queryWithPage = Object.assign({}, query, {
239
+ sort: "name:2",
240
+ offset: 1,
241
+ limit: 20
242
+ });
243
+ it('分页测试', function (){
244
+ return sampleDao.getList(queryWithPage).then(res =>{
245
+ res.should.to.be.instanceOf(Array);
246
+ })
247
+ });
248
+
249
+ let queryWithCustomQuery = Object.assign({}, query, {
250
+ customQuery: 'id & 1 = 1'
251
+ });
252
+
253
+ it('customQueryTest', function (){
254
+ return sampleDao.getList(queryWithCustomQuery).then(res =>{
255
+ res.should.to.be.instanceOf(Array);
256
+ })
257
+ });
258
+
259
+ let queryWithCustomQueryOnly = Object.assign({}, {
260
+ customQuery: 'id & 1 = 1'
261
+ });
262
+
263
+ it('customQueryTestOnly', function (){
264
+ return sampleDao.getList(queryWithCustomQueryOnly).then(res => {
265
+ res.should.to.be.instanceOf(Array);
266
+ })
267
+ });
268
+
269
+ let selectFieldsWithAs = Object.assign({}, {
270
+ selectFields: ['name as myName'],
271
+ });
272
+
273
+ it('selectFieldsWithAsTest', function (){
274
+ return sampleDao.getList(selectFieldsWithAs).then(res => {
275
+ res.should.to.be.instanceOf(Array);
276
+ })
277
+ });
278
+
279
+ let selectFieldsWithAsAndSort = Object.assign({}, {
280
+ selectFields: ['name as myName'],
281
+ sort: 'myName:1'
282
+ });
283
+
284
+ it('selectFieldsWithAsAndSortTest', function (){
285
+ return sampleDao.getList(selectFieldsWithAsAndSort).then(res => {
286
+ res.should.to.be.instanceOf(Array);
287
+ })
288
+ });
289
+
290
+ let selectFieldsWithAsAndKeywordAndSort = Object.assign({}, {
291
+ selectFields: ['*', 'name as myName'],
292
+ sort: 'myName:1',
293
+ keyword: 'myName:hello'
294
+ });
295
+
296
+ it('selectFieldsWithAsAndSortTest', function (){
297
+ return sampleDao.getList(selectFieldsWithAsAndKeywordAndSort).then(res => {
298
+ res.should.to.be.instanceOf(Array);
299
+ })
300
+ });
301
+
302
+ let selectFieldsWithAsAndKeywordAndSortAndInfieldsAndQuery = Object.assign({}, {
303
+ selectFields: ['*', 'SUBSTRING(name, INSTR(name,",") +1, +2) AS myName'],
304
+ sort: 'myName:1',
305
+ keyword: 'myName:hello',
306
+ inFields: {
307
+ myName: ['a', 'b']
308
+ },
309
+ customQuery: 'id & 1 = 1',
310
+ myName: 'c'
311
+ });
312
+
313
+ it('selectFieldsWithAsAndKeywordAndSortAndInfieldsAndQueryTest', function (){
314
+ return sampleDao.getList(selectFieldsWithAsAndKeywordAndSortAndInfieldsAndQuery).then(res => {
315
+ res.should.to.be.instanceOf(Array);
316
+ })
317
+ });
318
+ });
319
+
320
+ //findOne接口
321
+ describe('findOne', function(){
322
+ let query = {
323
+ selectFields: 'projectId',
324
+ projectId: 1,
325
+ offset: -1,
326
+ limit: 20
327
+ };
328
+ it('return One dashboard', function (){
329
+ return sampleDao.findOne(query).then(res =>{
330
+ res.should.to.be.an('object');
331
+ })
332
+ });
333
+ });
334
+
335
+ //getListByIds接口
336
+ describe('getListByIds', function(){
337
+ it('return dashboards', function (){
338
+ return sampleDao.getListByIds([id0, id1]).then(res =>{
339
+ res.should.to.be.instanceOf(Array);
340
+ })
341
+ });
342
+ it('如果ids为空的情况', function (){
343
+ return sampleDao.getListByIds().then(res =>{
344
+ res.should.to.be.instanceOf(Array);
345
+ })
346
+ });
347
+ });
348
+
349
+ describe('getCount', function(){
350
+ let query = {
351
+ projectId: 1,
352
+ keyword: {
353
+ name: 'sample'
354
+ }
355
+ };
356
+ it('return count', function(){
357
+ return sampleDao.getCount(Object.assign({}, {inFields: {
358
+ id: [id0, id1]
359
+ }})).then(res => {
360
+ res.should.to.be.a('number');
361
+ res.should.to.be.least(0);
362
+ })
363
+ });
364
+ it('return all count if query is {}', function(){
365
+ return sampleDao.getCount({}).then(res => {
366
+ res.should.to.be.a('number');
367
+ res.should.to.be.least(0);
368
+ })
369
+ });
370
+ });
371
+
372
+ //update接口
373
+ describe('update', function(){
374
+ it('更新数据', function (){
375
+ let sample = {
376
+ projectId: 2,
377
+ json: {
378
+ a: 1,
379
+ b: 2,
380
+ c: 3
381
+ }
382
+ };
383
+ return sampleDao.update(sample, id0).then(res =>{
384
+ res.should.to.be.equal('ok');
385
+ })
386
+ });
387
+ it('update with nullFields', function (){
388
+ let sample = {
389
+ projectId: 2,
390
+ nullFields: ['name', 'creatorId'],
391
+ name: null,
392
+ creatorId: undefined,
393
+ json: {
394
+ a: 1,
395
+ b: 2,
396
+ c: 3
397
+ }
398
+ };
399
+ return sampleDao.update(sample, id0).then(res =>{
400
+ res.should.to.be.equal('ok');
401
+ })
402
+ });
403
+ it('update with noUpdateTime', function (){
404
+ let sample = {
405
+ projectId: 2,
406
+ nullFields: ['name', 'creatorId'],
407
+ name: null,
408
+ noUpdateTime: true,
409
+ creatorId: undefined,
410
+ json: {
411
+ a: 1,
412
+ b: 2,
413
+ c: 3
414
+ }
415
+ };
416
+ return sampleDao.update(sample, id0).then(res =>{
417
+ res.should.to.be.equal('ok');
418
+ })
419
+ });
420
+ });
421
+
422
+ //updateByIds接口
423
+ describe('updateByIds', function(){
424
+ it('更新数据', function (){
425
+ let sample = {
426
+ projectId: 2,
427
+ json: {
428
+ a: 1,
429
+ b: 2,
430
+ c: 3
431
+ }
432
+ };
433
+ return sampleDao.updateByIds(sample, [id0, id1]).then(res =>{
434
+ res.should.to.be.equal('ok');
435
+ })
436
+ });
437
+ });
438
+
439
+ //updateByIds接口
440
+ describe('updateByQuery', function(){
441
+ it('更新数据', function (){
442
+ let sample = {
443
+ projectId: 2,
444
+ json: {
445
+ a: 1,
446
+ b: 2,
447
+ c: 3
448
+ }
449
+ };
450
+ return sampleDao.updateByQuery(sample, {projectId: 2, inFields: {id: [id0, id1]}}).then(res =>{
451
+ res.should.to.be.equal('ok');
452
+ })
453
+ });
454
+ it('不能无条件更新数据', function (){
455
+ let sample = {
456
+ projectId: 2,
457
+ json: {
458
+ a: 1,
459
+ b: 2,
460
+ c: 3
461
+ }
462
+ };
463
+ return sampleDao.updateByQuery(sample, {}).catch(err => {
464
+ console.log('message:', err.message);
465
+ err.message.should.to.equal('updateByQuery不能无条件update');
466
+ })
467
+ });
468
+ });
469
+
470
+
471
+ describe('updateBulk',function(){
472
+ it('使用updateBulk更新数据', function (){
473
+ let sample = {
474
+ projectId: 2,
475
+ id:id0,
476
+ json: {
477
+ a: 1,
478
+ b: 2,
479
+ c: 3
480
+ }
481
+ };
482
+ let sample1 = {
483
+ projectId: 2,
484
+ id:id1,
485
+ json: {
486
+ a: 1,
487
+ b: 2,
488
+ c: 3
489
+ }
490
+ };
491
+ return sampleDao.updateBulk([sample,sample1]).then(res =>{
492
+ res.should.to.be.equal('ok');
493
+ })
494
+ });
495
+ it('使用updateBulk更新空数据', function (){
496
+ return sampleDao.updateBulk([]).then(res =>{
497
+ res.should.to.be.equal('ok');
498
+ })
499
+ });
500
+ });
501
+
502
+
503
+ //delete接口
504
+ describe('delete', function(){
505
+ it('删除数据', function (){
506
+ return sampleDao.delete({inFields: {id: [id0]}}).then(res =>{
507
+ res.should.to.be.instanceOf(Object);
508
+ })
509
+ });
510
+ it('不能无条件的删除所有内容', function (){
511
+ return sampleDao.delete().catch(err =>{
512
+ err.code.should.to.equal(734);
513
+ })
514
+ });
515
+ });
516
+ //deleteByIds接口
517
+ describe('deleteByIds', function(){
518
+ it('根据id列表删除数据', function (){
519
+ return sampleDao.deleteByIds([id0, id1]).then(res =>{
520
+ res.should.to.be.instanceOf(Object);
521
+ })
522
+ });
523
+ it('如果ids为空,则返回undefined', function (){
524
+ return sampleDao.deleteByIds([]).then(res =>{
525
+ expect(res).to.be.an('undefined');
526
+ })
527
+ });
528
+ });
529
+
530
+ });
531
+
532
+
533
+
534
+
535
+
536
+ // userDao.get('id');
package/base/db.js CHANGED
@@ -23,6 +23,12 @@ let logSql = (connection, rows, sql, startTime, logExecuteTime) => {
23
23
  console.log(info);
24
24
  };
25
25
 
26
+ // 去掉报错信息行,只保留当前函数调用栈
27
+ let getCurrentStack = (currentStack) => {
28
+ // new Error().stack的格式是:Error: 错误信息\n at 函数名 (文件路径:行号:列号)... 去掉第一行即可获取当前函数的调用栈
29
+ return currentStack.split('\n').slice(1).join('\n');
30
+ };
31
+
26
32
  module.exports = (dbConfig, {log, noConvertDbCodes, dbCode, logExecuteTime}) => {
27
33
  let db = {
28
34
  pool: null
@@ -90,6 +96,7 @@ module.exports = (dbConfig, {log, noConvertDbCodes, dbCode, logExecuteTime}) =>
90
96
  };
91
97
 
92
98
  db.query = function (sql, sqlParam, connection) {
99
+ let currentStack = new Error().stack;
93
100
  let query;
94
101
  return new Promise(function (resolve, reject) {
95
102
  if(process.MYSQL_READ_ONLY && !sql.toLowerCase().trimLeft().startsWith('select')){
@@ -111,6 +118,7 @@ module.exports = (dbConfig, {log, noConvertDbCodes, dbCode, logExecuteTime}) =>
111
118
  logSql(connection, rows, query.sql, startTime, logExecuteTime);
112
119
  }
113
120
  err.code = dbCode;
121
+ err.stack = err.stack + getCurrentStack(currentStack);
114
122
  reject(err);
115
123
  } else {
116
124
  resolve(rows);
@@ -135,6 +143,7 @@ module.exports = (dbConfig, {log, noConvertDbCodes, dbCode, logExecuteTime}) =>
135
143
  }
136
144
  });
137
145
  }).catch(function (err) {
146
+ err.stack = err.stack + getCurrentStack(currentStack);
138
147
  reject(err);
139
148
  });
140
149
  }
package/base/dbUtil.js CHANGED
@@ -34,7 +34,7 @@ module.exports = (config, {dbCode = 733, ignoreDataError = false}) => {
34
34
  if(typeof keywordRes == 'string'){
35
35
  let [field, ...keyword] = keywordRes.split(':');
36
36
  keyword = keyword.join(':');
37
- orSqls.push(tableName + '.' + field + ' like ?');
37
+ orSqls.push(tableName + '.`' + field + '` like ?');
38
38
  if (keyword) {
39
39
  keyword = dbUtil.parseKeyword(keyword);
40
40
  }
@@ -43,7 +43,7 @@ module.exports = (config, {dbCode = 733, ignoreDataError = false}) => {
43
43
  Object.keys(keywordRes).map(field => {
44
44
  let subKeyword = keywordRes[field];
45
45
  if (subKeyword) {
46
- orSqls.push(tableName + '.' + field + ' like ?');
46
+ orSqls.push(tableName + '.`' + field + '` like ?');
47
47
  subKeyword = dbUtil.parseKeyword(subKeyword);
48
48
  params.push('%' + subKeyword + '%');
49
49
  }
@@ -59,7 +59,7 @@ module.exports = (config, {dbCode = 733, ignoreDataError = false}) => {
59
59
  if(insertFieldNameMap[field]){
60
60
  return '(' + insertFieldNameMap[field] + ')';
61
61
  }else{
62
- return tableName + '.' + field;
62
+ return tableName + '.' + '`' + field + '`';
63
63
  }
64
64
  };
65
65
 
@@ -191,11 +191,16 @@ module.exports = (config, {dbCode = 733, ignoreDataError = false}) => {
191
191
 
192
192
  if (!obj.create_time && fieldNames.includes('create_time')){
193
193
  obj.create_time = new Date();
194
- addFieldNames.push('create_time');
194
+ if (!addFieldNames.includes('create_time')) {
195
+ addFieldNames.push('create_time');
196
+ }
195
197
  }
198
+
196
199
  if (!obj.modify_time && fieldNames.includes('modify_time')){
197
200
  obj.modify_time = new Date();
198
- addFieldNames.push('modify_time');
201
+ if (!addFieldNames.includes('modify_time')) {
202
+ addFieldNames.push('modify_time');
203
+ }
199
204
  }
200
205
 
201
206
  let sql = `INSERT INTO ${tableName} (${addFieldNames.map(field => '`' + field + '`').join(',')}) VALUES(?)`;
@@ -235,7 +240,7 @@ module.exports = (config, {dbCode = 733, ignoreDataError = false}) => {
235
240
  });
236
241
 
237
242
 
238
- let sql = 'INSERT INTO ' + tableName + '(' + addFieldNames.join(',') + ')' + ' VALUES ?';
243
+ let sql = 'INSERT INTO ' + tableName + '(' + addFieldNames.map(field => '`' + field + '`').join(',') + ')' + ' VALUES ?';
239
244
  let params = objs.map(obj => addFieldNames.map(fieldName => obj[fieldName]));
240
245
  return {
241
246
  params: [params],
@@ -351,7 +356,7 @@ module.exports = (config, {dbCode = 733, ignoreDataError = false}) => {
351
356
  let value = obj[fieldName];
352
357
  if (nullFields.includes(fieldName) || !util.isNullOrUndefined(value)) {
353
358
  params.push(value);
354
- updateArr.push(fieldName + '=?');
359
+ updateArr.push('`' + fieldName + '`' + ' =?');
355
360
  }
356
361
  });
357
362
  }
@@ -387,7 +392,7 @@ module.exports = (config, {dbCode = 733, ignoreDataError = false}) => {
387
392
  obj.modify_time = new Date();
388
393
  });
389
394
  fieldNames = fieldNames.filter(fieldName => !util.isUndefined(objs[0][fieldName]));
390
- let sql = 'INSERT INTO ' + tableName + '(' + fieldNames.join(',') + ')' + ' VALUES ?';
395
+ let sql = 'INSERT INTO ' + tableName + '(' + fieldNames.map(fieldName => '`' + fieldName + '`').join(',') + ')' + ' VALUES ?';
391
396
  let params = objs.map(obj => fieldNames.map(fieldName => obj[fieldName]));
392
397
  let updateField = [];
393
398
  fieldNames.forEach(function (field) {
@@ -436,7 +441,7 @@ module.exports = (config, {dbCode = 733, ignoreDataError = false}) => {
436
441
  toSelectFields.push(field);
437
442
  }else {
438
443
  if(field !== '*'){
439
- field = dbUtil.toDbFieldNames(tableName, [field])[0];
444
+ field = '`' + dbUtil.toDbFieldNames(tableName, [field])[0] + '`';
440
445
  }
441
446
  toSelectFields.push(tableName + '.' + field);
442
447
  }
package/base/err.js CHANGED
@@ -6,4 +6,5 @@ module.exports = function (message, code, value){
6
6
  this.message = message;
7
7
  this.code = code || 500;
8
8
  this.value = value || '';
9
+ Error.captureStackTrace(this);
9
10
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dborm-mysql",
3
- "version": "2.1.4",
3
+ "version": "2.2.1",
4
4
  "description": "a NodeJs ORM for mysql",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",