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.
- package/README.md +29 -1
- package/dist/req-mingo.umd.js +1 -1
- package/dist/w-orm-lmdb.umd.js +2 -2
- package/dist/w-orm-lmdb.umd.js.map +1 -1
- package/docs/WOrmLmdb.html +172 -7
- package/docs/WOrmLmdb.mjs.html +100 -5
- package/docs/index.html +2 -2
- package/g-basic.mjs +28 -0
- package/package.json +1 -1
- package/src/WOrmLmdb.mjs +98 -3
- package/test/unit-insertbulk.test.mjs +205 -0
- package//350/263/207/346/226/231/345/272/253/345/207/275/346/225/270/345/233/236/345/202/263/345/256/232/347/276/251/350/250/210/347/256/227.md +129 -32
package/docs/WOrmLmdb.mjs.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
|
|
|
@@ -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) && !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
|
|
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
|
|
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
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
|
+
})
|