w-orm-lmdb 1.0.18 → 1.0.19

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.
@@ -29,7 +29,7 @@
29
29
  <nav >
30
30
 
31
31
 
32
- <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WOrmLmdb.html">WOrmLmdb</a><ul class='methods'><li data-type='method'><a href="WOrmLmdb.html#.del">del</a></li><li data-type='method'><a href="WOrmLmdb.html#.delAll">delAll</a></li><li data-type='method'><a href="WOrmLmdb.html#.insert">insert</a></li><li data-type='method'><a href="WOrmLmdb.html#.save">save</a></li><li data-type='method'><a href="WOrmLmdb.html#.select">select</a></li><li data-type='method'><a href="WOrmLmdb.html#.selectByPk">selectByPk</a></li></ul></li></ul>
32
+ <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WOrmLmdb.html">WOrmLmdb</a><ul class='methods'><li data-type='method'><a href="WOrmLmdb.html#.del">del</a></li><li data-type='method'><a href="WOrmLmdb.html#.delAll">delAll</a></li><li data-type='method'><a href="WOrmLmdb.html#.insert">insert</a></li><li data-type='method'><a href="WOrmLmdb.html#.insertBulk">insertBulk</a></li><li data-type='method'><a href="WOrmLmdb.html#.save">save</a></li><li data-type='method'><a href="WOrmLmdb.html#.select">select</a></li><li data-type='method'><a href="WOrmLmdb.html#.selectByPk">selectByPk</a></li></ul></li></ul>
33
33
 
34
34
  </nav>
35
35
 
@@ -45,7 +45,7 @@
45
45
 
46
46
  <section>
47
47
  <article>
48
- <pre class="prettyprint source linenums"><code>import { open } from 'lmdb'
48
+ <pre class="prettyprint source linenums"><code>import { open, ABORT } from 'lmdb'
49
49
  // import mingo from 'mingo' //mingo內未更新import寫法, 會導致ERR_UNSUPPORTED_DIR_IMPORT, 故須改用require引入使用
50
50
  import mingo from './reqMingo.js'
51
51
  import size from 'lodash-es/size.js'
@@ -75,13 +75,13 @@ import waitFun from 'wsemi/src/waitFun.mjs'
75
75
  * 故不監聽亦能取得完整資訊,且監聽與否不改變任何操作之回傳值。
76
76
  *
77
77
  * change事件,參數為(mode, data, res),於資料實際異動成功後發出:
78
- * mode為操作別字串,可為'insert'、'save'、'del'、'delAll';save內若逐筆走自動插入則該筆另發出mode為'insert'之事件。
78
+ * mode為操作別字串,可為'insert'、'insertBulk'、'save'、'del'、'delAll';save內若逐筆走自動插入則該筆另發出mode為'insert'之事件。
79
79
  * data為本次操作之輸入數據,delAll固定為null。
80
80
  * res為本次操作之回傳結果。
81
81
  * 逐筆函數以整批為單位發出一次而不逐筆發出,select與selectByPk不發出本事件。
82
82
  *
83
83
  * error事件,參數為(mode, data, err),於操作發生錯誤時發出:
84
- * mode為操作別字串,可為'select'、'selectByPk'、'insert'、'save'、'del'、'delAll'。
84
+ * mode為操作別字串,可為'select'、'selectByPk'、'insert'、'insertBulk'、'save'、'del'、'delAll'。
85
85
  * data為本次操作之輸入數據,無輸入數據者為null。
86
86
  * err為錯誤訊息字串,內容與正規管道所送出者一致。
87
87
  * 整批性錯誤於reject之前發出;逐筆失敗於該筆結果定案後發出,每筆一次。
@@ -454,6 +454,100 @@ function WOrmLmdb(opt = {}) {
454
454
  return res
455
455
  }
456
456
 
457
+ /**
458
+ * 批次插入數據,全批視為一個單位,全部插入成功或一筆都不寫入
459
+ * 註: 本函數非insert之加速版,兩者衝突政策不同。insert於主鍵已存在時跳過該筆而整批ok為1,
460
+ * 本函數則整批reject且不寫入任何一筆;同批含重複主鍵者亦視為衝突。確無衝突時兩者結果相同
461
+ * 註: 於本套件不會較insert快,因insert本即以Promise.all一次送出全部條件寫入而非逐筆await,
462
+ * 提供本函數係為與其他w-orm系列套件維持同一組函數,令呼叫端得於各套件間替換而不須改寫呼叫
463
+ *
464
+ * @memberOf WOrmLmdb
465
+ * @param {Object|Array} data 輸入數據物件或陣列
466
+ * @returns {Promise} 回傳Promise,resolve回傳插入結果物件{n,nInserted,ok},n為輸入筆數、nInserted成功時恆等於n,任一筆主鍵已存在則reject回傳錯誤訊息
467
+ */
468
+ async function insertBulk(data) {
469
+ let isErr = false
470
+
471
+ //check
472
+ if (!iseobj(data) &amp;&amp; !isearr(data)) {
473
+ return {
474
+ n: 0,
475
+ nInserted: 0,
476
+ ok: 1,
477
+ }
478
+ }
479
+
480
+ //cloneDeep, 與外部數據脫勾
481
+ data = cloneDeep(data)
482
+
483
+ //res
484
+ let res = null
485
+ try {
486
+
487
+ //check
488
+ if (!isarr(data)) {
489
+ data = [data]
490
+ }
491
+
492
+ //check id
493
+ data = procPk(data, 'insertBulk')
494
+
495
+ //nAll
496
+ let nAll = size(data)
497
+
498
+ //childTransaction, 全有全無由交易回滾保證
499
+ //註: 非同步之client.transaction於中止時並不回滾, 實測其內之put仍會落盤, 故此處須用childTransaction
500
+ //註: 交易內之client.get讀得到同一交易稍早之put, 故同批含重複主鍵者亦會於此被偵測為衝突
501
+ //註: 存在與否採鍵層判定, 與insert之ifNoExists一致
502
+ let pkConflict = null
503
+ await client.childTransaction(() => {
504
+ for (let v of data) {
505
+ if (client.get(v.id) !== undefined) {
506
+ pkConflict = v.id
507
+ return ABORT
508
+ }
509
+ client.put(v.id, v)
510
+ }
511
+ })
512
+
513
+ //check, 衝突則整批視為失敗, 交易已回滾故無任何寫入
514
+ if (isestr(pkConflict)) {
515
+ throw new Error(`can not insertBulk by existed id[${pkConflict}]`)
516
+ }
517
+
518
+ //res, 未衝突則全數插入, 故nInserted恆等於n
519
+ res = {
520
+ n: nAll,
521
+ nInserted: nAll,
522
+ ok: 1,
523
+ }
524
+
525
+ }
526
+ catch (err) {
527
+ isErr = true
528
+ res = err
529
+ }
530
+
531
+ //update, 不能保證插入多少, 一律重設快取
532
+ _cache = null
533
+
534
+ //emit, 於change可能須使用select, 故須放在重設快取之後
535
+ if (!isErr) {
536
+ emitChange('insertBulk', data, res)
537
+ }
538
+
539
+ //check
540
+ if (isErr) {
541
+
542
+ //emit, 整批性錯誤須於reject之前發出
543
+ emitError('insertBulk', data, res)
544
+
545
+ return Promise.reject(res)
546
+ }
547
+
548
+ return res
549
+ }
550
+
457
551
  /**
458
552
  * 儲存數據
459
553
  *
@@ -909,6 +1003,7 @@ function WOrmLmdb(opt = {}) {
909
1003
  ee.select = select
910
1004
  ee.selectByPk = selectByPk
911
1005
  ee.insert = insert
1006
+ ee.insertBulk = insertBulk
912
1007
  ee.save = save
913
1008
  ee.del = del
914
1009
  ee.delAll = delAll
@@ -933,7 +1028,7 @@ export default WOrmLmdb
933
1028
  <br class="clear">
934
1029
 
935
1030
  <footer>
936
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Mon Aug 17 2026 08:38:27 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1031
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Mon Aug 17 2026 11:00:07 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
937
1032
  </footer>
938
1033
 
939
1034
  <script>prettyPrint();</script>
package/docs/index.html CHANGED
@@ -29,7 +29,7 @@
29
29
  <nav >
30
30
 
31
31
 
32
- <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WOrmLmdb.html">WOrmLmdb</a><ul class='methods'><li data-type='method'><a href="WOrmLmdb.html#.del">del</a></li><li data-type='method'><a href="WOrmLmdb.html#.delAll">delAll</a></li><li data-type='method'><a href="WOrmLmdb.html#.insert">insert</a></li><li data-type='method'><a href="WOrmLmdb.html#.save">save</a></li><li data-type='method'><a href="WOrmLmdb.html#.select">select</a></li><li data-type='method'><a href="WOrmLmdb.html#.selectByPk">selectByPk</a></li></ul></li></ul>
32
+ <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WOrmLmdb.html">WOrmLmdb</a><ul class='methods'><li data-type='method'><a href="WOrmLmdb.html#.del">del</a></li><li data-type='method'><a href="WOrmLmdb.html#.delAll">delAll</a></li><li data-type='method'><a href="WOrmLmdb.html#.insert">insert</a></li><li data-type='method'><a href="WOrmLmdb.html#.insertBulk">insertBulk</a></li><li data-type='method'><a href="WOrmLmdb.html#.save">save</a></li><li data-type='method'><a href="WOrmLmdb.html#.select">select</a></li><li data-type='method'><a href="WOrmLmdb.html#.selectByPk">selectByPk</a></li></ul></li></ul>
33
33
 
34
34
  </nav>
35
35
 
@@ -71,7 +71,7 @@
71
71
  <br class="clear">
72
72
 
73
73
  <footer>
74
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Mon Aug 17 2026 08:38:27 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
74
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Mon Aug 17 2026 11:00:07 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
75
75
  </footer>
76
76
 
77
77
  <script>prettyPrint();</script>
package/g-basic.mjs CHANGED
@@ -157,6 +157,29 @@ async function test() {
157
157
  console.log('del by data without id catch', msg)
158
158
  })
159
159
 
160
+ //insertBulk, 全批視為一個單位, 無衝突時nInserted恆等於n
161
+ await wo.insertBulk([{ id: 'id-bulk1', name: 'bulk1' }, { id: 'id-bulk2', name: 'bulk2' }])
162
+ .then(function(msg) {
163
+ console.log('insertBulk then', msg)
164
+ })
165
+ .catch(function(msg) {
166
+ console.log('insertBulk catch', msg)
167
+ })
168
+
169
+ //insertBulk by data with existed id, 非insert之加速版而係衝突政策不同
170
+ //insert於主鍵已存在時跳過該筆而整批ok為1, insertBulk則整批reject且不寫入任何一筆
171
+ await wo.insertBulk([{ id: 'id-bulk3', name: 'bulk3' }, { id: 'id-peter', name: 'conflict' }])
172
+ .then(function(msg) {
173
+ console.log('insertBulk by data with existed id then', msg)
174
+ })
175
+ .catch(function(msg) {
176
+ console.log('insertBulk by data with existed id catch', msg.toString())
177
+ })
178
+
179
+ //select all, 可見id-bulk3因整批reject而未寫入
180
+ let sb2 = await wo.select()
181
+ console.log('ids after insertBulk', _.map(_.sortBy(sb2, 'id'), 'id'))
182
+
160
183
  }
161
184
  test()
162
185
  // change delAll
@@ -208,6 +231,11 @@ test()
208
231
  // error del can not delete by invalid id[]
209
232
  // change del
210
233
  // del by data without id then [ { n: 0, nDeleted: 0, ok: 0, err: 'can not delete by invalid id[]' } ]
234
+ // change insertBulk
235
+ // insertBulk then { n: 2, nInserted: 2, ok: 1 }
236
+ // error insertBulk can not insertBulk by existed id[id-peter]
237
+ // insertBulk by data with existed id catch Error: can not insertBulk by existed id[id-peter]
238
+ // ids after insertBulk [ 'id-bulk1', 'id-bulk2', 'id-peter', 'id-rosemary' ]
211
239
 
212
240
 
213
241
  //node g-basic.mjs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "w-orm-lmdb",
3
- "version": "1.0.18",
3
+ "version": "1.0.19",
4
4
  "main": "dist/w-orm-lmdb.umd.js",
5
5
  "dependencies": {
6
6
  "lmdb": "^3.5.6",
package/src/WOrmLmdb.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { open } from 'lmdb'
1
+ import { open, ABORT } from 'lmdb'
2
2
  // import mingo from 'mingo' //mingo內未更新import寫法, 會導致ERR_UNSUPPORTED_DIR_IMPORT, 故須改用require引入使用
3
3
  import mingo from './reqMingo.js'
4
4
  import size from 'lodash-es/size.js'
@@ -28,13 +28,13 @@ import waitFun from 'wsemi/src/waitFun.mjs'
28
28
  * 故不監聽亦能取得完整資訊,且監聽與否不改變任何操作之回傳值。
29
29
  *
30
30
  * change事件,參數為(mode, data, res),於資料實際異動成功後發出:
31
- * mode為操作別字串,可為'insert'、'save'、'del'、'delAll';save內若逐筆走自動插入則該筆另發出mode為'insert'之事件。
31
+ * mode為操作別字串,可為'insert'、'insertBulk'、'save'、'del'、'delAll';save內若逐筆走自動插入則該筆另發出mode為'insert'之事件。
32
32
  * data為本次操作之輸入數據,delAll固定為null。
33
33
  * res為本次操作之回傳結果。
34
34
  * 逐筆函數以整批為單位發出一次而不逐筆發出,select與selectByPk不發出本事件。
35
35
  *
36
36
  * error事件,參數為(mode, data, err),於操作發生錯誤時發出:
37
- * mode為操作別字串,可為'select'、'selectByPk'、'insert'、'save'、'del'、'delAll'。
37
+ * mode為操作別字串,可為'select'、'selectByPk'、'insert'、'insertBulk'、'save'、'del'、'delAll'。
38
38
  * data為本次操作之輸入數據,無輸入數據者為null。
39
39
  * err為錯誤訊息字串,內容與正規管道所送出者一致。
40
40
  * 整批性錯誤於reject之前發出;逐筆失敗於該筆結果定案後發出,每筆一次。
@@ -407,6 +407,100 @@ function WOrmLmdb(opt = {}) {
407
407
  return res
408
408
  }
409
409
 
410
+ /**
411
+ * 批次插入數據,全批視為一個單位,全部插入成功或一筆都不寫入
412
+ * 註: 本函數非insert之加速版,兩者衝突政策不同。insert於主鍵已存在時跳過該筆而整批ok為1,
413
+ * 本函數則整批reject且不寫入任何一筆;同批含重複主鍵者亦視為衝突。確無衝突時兩者結果相同
414
+ * 註: 於本套件不會較insert快,因insert本即以Promise.all一次送出全部條件寫入而非逐筆await,
415
+ * 提供本函數係為與其他w-orm系列套件維持同一組函數,令呼叫端得於各套件間替換而不須改寫呼叫
416
+ *
417
+ * @memberOf WOrmLmdb
418
+ * @param {Object|Array} data 輸入數據物件或陣列
419
+ * @returns {Promise} 回傳Promise,resolve回傳插入結果物件{n,nInserted,ok},n為輸入筆數、nInserted成功時恆等於n,任一筆主鍵已存在則reject回傳錯誤訊息
420
+ */
421
+ async function insertBulk(data) {
422
+ let isErr = false
423
+
424
+ //check
425
+ if (!iseobj(data) && !isearr(data)) {
426
+ return {
427
+ n: 0,
428
+ nInserted: 0,
429
+ ok: 1,
430
+ }
431
+ }
432
+
433
+ //cloneDeep, 與外部數據脫勾
434
+ data = cloneDeep(data)
435
+
436
+ //res
437
+ let res = null
438
+ try {
439
+
440
+ //check
441
+ if (!isarr(data)) {
442
+ data = [data]
443
+ }
444
+
445
+ //check id
446
+ data = procPk(data, 'insertBulk')
447
+
448
+ //nAll
449
+ let nAll = size(data)
450
+
451
+ //childTransaction, 全有全無由交易回滾保證
452
+ //註: 非同步之client.transaction於中止時並不回滾, 實測其內之put仍會落盤, 故此處須用childTransaction
453
+ //註: 交易內之client.get讀得到同一交易稍早之put, 故同批含重複主鍵者亦會於此被偵測為衝突
454
+ //註: 存在與否採鍵層判定, 與insert之ifNoExists一致
455
+ let pkConflict = null
456
+ await client.childTransaction(() => {
457
+ for (let v of data) {
458
+ if (client.get(v.id) !== undefined) {
459
+ pkConflict = v.id
460
+ return ABORT
461
+ }
462
+ client.put(v.id, v)
463
+ }
464
+ })
465
+
466
+ //check, 衝突則整批視為失敗, 交易已回滾故無任何寫入
467
+ if (isestr(pkConflict)) {
468
+ throw new Error(`can not insertBulk by existed id[${pkConflict}]`)
469
+ }
470
+
471
+ //res, 未衝突則全數插入, 故nInserted恆等於n
472
+ res = {
473
+ n: nAll,
474
+ nInserted: nAll,
475
+ ok: 1,
476
+ }
477
+
478
+ }
479
+ catch (err) {
480
+ isErr = true
481
+ res = err
482
+ }
483
+
484
+ //update, 不能保證插入多少, 一律重設快取
485
+ _cache = null
486
+
487
+ //emit, 於change可能須使用select, 故須放在重設快取之後
488
+ if (!isErr) {
489
+ emitChange('insertBulk', data, res)
490
+ }
491
+
492
+ //check
493
+ if (isErr) {
494
+
495
+ //emit, 整批性錯誤須於reject之前發出
496
+ emitError('insertBulk', data, res)
497
+
498
+ return Promise.reject(res)
499
+ }
500
+
501
+ return res
502
+ }
503
+
410
504
  /**
411
505
  * 儲存數據
412
506
  *
@@ -862,6 +956,7 @@ function WOrmLmdb(opt = {}) {
862
956
  ee.select = select
863
957
  ee.selectByPk = selectByPk
864
958
  ee.insert = insert
959
+ ee.insertBulk = insertBulk
865
960
  ee.save = save
866
961
  ee.del = del
867
962
  ee.delAll = delAll
@@ -0,0 +1,205 @@
1
+ import assert from 'assert'
2
+ import _ from 'lodash-es'
3
+ import w from 'wsemi'
4
+ import WOrm from '../src/WOrmLmdb.mjs'
5
+
6
+
7
+ describe('insertBulk', function() {
8
+ let rt = null
9
+ let vans = {}
10
+ let vget = {}
11
+
12
+ before(async function() {
13
+
14
+ w.fsDeleteFolder('./_db_insertbulk')
15
+
16
+ let url = './_db_insertbulk'
17
+
18
+ let wo = WOrm({ url, db: 'worm', cl: 'users' })
19
+
20
+ //輸入無效
21
+ vget[1] = await wo.insertBulk(null)
22
+
23
+ //正常插入, nInserted須恆等於n
24
+ rt = null
25
+ // vans[2] = { n: 3, nInserted: 3, ok: 1 }
26
+ await wo.insertBulk([{ id: 'a' }, { id: 'b' }, { id: 'c' }])
27
+ .then(function(msg) {
28
+ // console.log('insertBulk then', msg)
29
+ // insertBulk then { n: 3, nInserted: 3, ok: 1 }
30
+ rt = msg
31
+ })
32
+ .catch(function(msg) {
33
+ // console.log('insertBulk catch', msg)
34
+ rt = 'reject: ' + msg.toString()
35
+ })
36
+ vget[2] = rt
37
+ vget[3] = _.map(_.sortBy(await wo.select(), 'id'), 'id')
38
+
39
+ //單一物件亦須回傳單一物件而非陣列
40
+ rt = null
41
+ // vans[4] = { n: 1, nInserted: 1, ok: 1 }
42
+ await wo.insertBulk({ id: 'd' })
43
+ .then(function(msg) {
44
+ rt = msg
45
+ })
46
+ .catch(function(msg) {
47
+ rt = 'reject: ' + msg.toString()
48
+ })
49
+ vget[4] = rt
50
+
51
+ //含既有主鍵須整批reject, 且不得寫入任何一筆
52
+ rt = null
53
+ await wo.insertBulk([{ id: 'e' }, { id: 'a' }, { id: 'f' }])
54
+ .then(function(msg) {
55
+ rt = 'resolve: ' + JSON.stringify(msg)
56
+ })
57
+ .catch(function() {
58
+ rt = 'reject'
59
+ })
60
+ vget[5] = rt
61
+ vget[6] = _.map(_.sortBy(await wo.select(), 'id'), 'id')
62
+
63
+ //同批含重複主鍵亦視為衝突
64
+ rt = null
65
+ await wo.insertBulk([{ id: 'g' }, { id: 'g' }])
66
+ .then(function(msg) {
67
+ rt = 'resolve: ' + JSON.stringify(msg)
68
+ })
69
+ .catch(function() {
70
+ rt = 'reject'
71
+ })
72
+ vget[7] = rt
73
+ vget[8] = _.map(_.sortBy(await wo.select(), 'id'), 'id')
74
+
75
+ //事件: 成功發change, 衝突發error且不發change
76
+ let evs = []
77
+ wo.on('change', function(mode) {
78
+ evs.push('change:' + mode)
79
+ })
80
+ wo.on('error', function(mode, data, err) {
81
+ evs.push({ ev: 'error:' + mode, isStr: _.isString(err) })
82
+ })
83
+ await wo.insertBulk({ id: 'h' })
84
+ vget[9] = _.map(evs, function(v) {
85
+ return v.ev || v
86
+ })
87
+ evs = []
88
+ await wo.insertBulk({ id: 'h' }).catch(function() {})
89
+ vget[10] = _.map(evs, function(v) {
90
+ return v.ev || v
91
+ })
92
+ vget[11] = _.get(evs, '0.isStr')
93
+ await wo.close()
94
+
95
+ //autoGenPk為true時補值
96
+ let woGen = WOrm({ url, db: 'worm', cl: 'gen' })
97
+ rt = null
98
+ // vans[12] = { n: 2, nInserted: 2, ok: 1 }
99
+ await woGen.insertBulk([{ v: 1 }, { v: 2 }])
100
+ .then(function(msg) {
101
+ rt = msg
102
+ })
103
+ .catch(function(msg) {
104
+ rt = 'reject: ' + msg.toString()
105
+ })
106
+ vget[12] = rt
107
+ vget[13] = _.size(_.filter(await woGen.select(), function(v) {
108
+ return w.isestr(v.id)
109
+ }))
110
+ await woGen.close()
111
+
112
+ //autoGenPk為false而未帶有效主鍵, 須reject且不得寫入任何一筆
113
+ let woNo = WOrm({ url, db: 'worm', cl: 'nogen', autoGenPk: false })
114
+ rt = null
115
+ await woNo.insertBulk([{ id: 'x1' }, { v: 1 }])
116
+ .then(function(msg) {
117
+ rt = 'resolve: ' + JSON.stringify(msg)
118
+ })
119
+ .catch(function() {
120
+ rt = 'reject'
121
+ })
122
+ vget[14] = rt
123
+ vget[15] = _.size(await woNo.select())
124
+ await woNo.close()
125
+
126
+ })
127
+
128
+ vans[1] = { n: 0, nInserted: 0, ok: 1 }
129
+ it(`should get ${JSON.stringify(vans[1])} for insertBulk with invalid input`, async function() {
130
+ assert.strict.deepStrictEqual(vget[1], vans[1])
131
+ })
132
+
133
+ vans[2] = { n: 3, nInserted: 3, ok: 1 }
134
+ it(`should get ${JSON.stringify(vans[2])} for insertBulk without conflict`, async function() {
135
+ assert.strict.deepStrictEqual(vget[2], vans[2])
136
+ })
137
+
138
+ vans[3] = ['a', 'b', 'c']
139
+ it(`should get ${JSON.stringify(vans[3])} for records after insertBulk`, async function() {
140
+ assert.strict.deepStrictEqual(vget[3], vans[3])
141
+ })
142
+
143
+ vans[4] = { n: 1, nInserted: 1, ok: 1 }
144
+ it(`should get ${JSON.stringify(vans[4])} for insertBulk by single object`, async function() {
145
+ assert.strict.deepStrictEqual(vget[4], vans[4])
146
+ })
147
+
148
+ //全有全無: 衝突須整批reject
149
+ vans[5] = 'reject'
150
+ it(`should get ${JSON.stringify(vans[5])} for insertBulk with existed id`, async function() {
151
+ assert.strict.deepStrictEqual(vget[5], vans[5])
152
+ })
153
+
154
+ //全有全無: 衝突時同批之無衝突筆數亦不得寫入
155
+ vans[6] = ['a', 'b', 'c', 'd']
156
+ it(`should get ${JSON.stringify(vans[6])} for no writing when insertBulk rejected`, async function() {
157
+ assert.strict.deepStrictEqual(vget[6], vans[6])
158
+ })
159
+
160
+ vans[7] = 'reject'
161
+ it(`should get ${JSON.stringify(vans[7])} for insertBulk with duplicated id in same batch`, async function() {
162
+ assert.strict.deepStrictEqual(vget[7], vans[7])
163
+ })
164
+
165
+ vans[8] = ['a', 'b', 'c', 'd']
166
+ it(`should get ${JSON.stringify(vans[8])} for no writing when duplicated id in same batch`, async function() {
167
+ assert.strict.deepStrictEqual(vget[8], vans[8])
168
+ })
169
+
170
+ vans[9] = ['change:insertBulk']
171
+ it(`should get ${JSON.stringify(vans[9])} for change event of insertBulk`, async function() {
172
+ assert.strict.deepStrictEqual(vget[9], vans[9])
173
+ })
174
+
175
+ vans[10] = ['error:insertBulk']
176
+ it(`should get ${JSON.stringify(vans[10])} for error event of insertBulk with conflict`, async function() {
177
+ assert.strict.deepStrictEqual(vget[10], vans[10])
178
+ })
179
+
180
+ vans[11] = true
181
+ it(`should get ${JSON.stringify(vans[11])} for err of error event being string`, async function() {
182
+ assert.strict.deepStrictEqual(vget[11], vans[11])
183
+ })
184
+
185
+ vans[12] = { n: 2, nInserted: 2, ok: 1 }
186
+ it(`should get ${JSON.stringify(vans[12])} for insertBulk without id by autoGenPk=true`, async function() {
187
+ assert.strict.deepStrictEqual(vget[12], vans[12])
188
+ })
189
+
190
+ vans[13] = 2
191
+ it(`should get ${JSON.stringify(vans[13])} for records with generated id`, async function() {
192
+ assert.strict.deepStrictEqual(vget[13], vans[13])
193
+ })
194
+
195
+ vans[14] = 'reject'
196
+ it(`should get ${JSON.stringify(vans[14])} for insertBulk without id by autoGenPk=false`, async function() {
197
+ assert.strict.deepStrictEqual(vget[14], vans[14])
198
+ })
199
+
200
+ vans[15] = 0
201
+ it(`should get ${JSON.stringify(vans[15])} for no writing when autoGenPk=false rejected`, async function() {
202
+ assert.strict.deepStrictEqual(vget[15], vans[15])
203
+ })
204
+
205
+ })