w-orm-reladb 1.1.6 → 1.1.8
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 +25 -3
- package/dist/w-orm-reladb.umd.js +2 -2
- package/dist/w-orm-reladb.umd.js.map +1 -1
- package/docs/WOrmReladb.html +39 -21
- package/docs/WOrmReladb.mjs.html +206 -131
- package/docs/cvFind.mjs.html +861 -0
- package/docs/global.html +1716 -0
- package/docs/importModels.mjs.html +255 -0
- package/docs/index.html +2 -2
- package/g-mssql.mjs +1 -1
- package/g-sqlite-encryption.mjs +1 -1
- package/g-sqlite.mjs +1 -1
- package/models/tcond.js +74 -0
- package/models/tpkdec.js +20 -0
- package/models/tpkint.js +20 -0
- package/package.json +3 -3
- package/src/WOrmReladb.mjs +204 -129
- package/src/cvFind.mjs +789 -0
- package/src/importModels.mjs +180 -114
- package/src/requireModel.js +13 -5
- package/test/api-dist.test.mjs +112 -0
- package/test/api-init.test.mjs +50 -0
- package/test/api-models.test.mjs +216 -0
- package/test/api-suite.mjs +492 -3
- package/test/tools/modelsWorker.mjs +35 -0
- package/test/unit-cvfind.test.mjs +393 -0
- package/toolg/gDistRollup.mjs +2 -0
- package/src/modifyModel.mjs +0 -113
package/docs/WOrmReladb.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="WOrmReladb.html">WOrmReladb</a><ul class='methods'><li data-type='method'><a href="WOrmReladb.html#.closeSequelize">closeSequelize</a></li><li data-type='method'><a href="WOrmReladb.html#.createStorage">createStorage</a></li><li data-type='method'><a href="WOrmReladb.html#.del">del</a></li><li data-type='method'><a href="WOrmReladb.html#.delAll">delAll</a></li><li data-type='method'><a href="WOrmReladb.html#.genModelsByDB">genModelsByDB</a></li><li data-type='method'><a href="WOrmReladb.html#.genModelsByTabs">genModelsByTabs</a></li><li data-type='method'><a href="WOrmReladb.html#.genTransaction">genTransaction</a></li><li data-type='method'><a href="WOrmReladb.html#.initSequelize">initSequelize</a></li><li data-type='method'><a href="WOrmReladb.html#.insert">insert</a></li><li data-type='method'><a href="WOrmReladb.html#.insertBulk">insertBulk</a></li><li data-type='method'><a href="WOrmReladb.html#.save">save</a></li><li data-type='method'><a href="WOrmReladb.html#.select">select</a></li><li data-type='method'><a href="WOrmReladb.html#.selectByPk">selectByPk</a></li></ul></li></ul>
|
|
32
|
+
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WOrmReladb.html">WOrmReladb</a><ul class='methods'><li data-type='method'><a href="WOrmReladb.html#.closeSequelize">closeSequelize</a></li><li data-type='method'><a href="WOrmReladb.html#.createStorage">createStorage</a></li><li data-type='method'><a href="WOrmReladb.html#.del">del</a></li><li data-type='method'><a href="WOrmReladb.html#.delAll">delAll</a></li><li data-type='method'><a href="WOrmReladb.html#.genModelsByDB">genModelsByDB</a></li><li data-type='method'><a href="WOrmReladb.html#.genModelsByTabs">genModelsByTabs</a></li><li data-type='method'><a href="WOrmReladb.html#.genTransaction">genTransaction</a></li><li data-type='method'><a href="WOrmReladb.html#.initSequelize">initSequelize</a></li><li data-type='method'><a href="WOrmReladb.html#.insert">insert</a></li><li data-type='method'><a href="WOrmReladb.html#.insertBulk">insertBulk</a></li><li data-type='method'><a href="WOrmReladb.html#.save">save</a></li><li data-type='method'><a href="WOrmReladb.html#.select">select</a></li><li data-type='method'><a href="WOrmReladb.html#.selectByPk">selectByPk</a></li></ul></li></ul><h3>Global</h3><ul><li><a href="global.html#cvFind">cvFind</a></li><li><a href="global.html#getColKind">getColKind</a></li><li><a href="global.html#getColScale">getColScale</a></li><li><a href="global.html#importModels">importModels</a></li><li><a href="global.html#isKindOk">isKindOk</a></li><li><a href="global.html#normPk">normPk</a></li></ul>
|
|
33
33
|
|
|
34
34
|
</nav>
|
|
35
35
|
|
|
@@ -50,7 +50,6 @@ import Sequelize from 'sequelize'
|
|
|
50
50
|
import cloneDeep from 'lodash-es/cloneDeep.js'
|
|
51
51
|
import get from 'lodash-es/get.js'
|
|
52
52
|
import map from 'lodash-es/map.js'
|
|
53
|
-
import each from 'lodash-es/each.js'
|
|
54
53
|
import size from 'lodash-es/size.js'
|
|
55
54
|
import split from 'lodash-es/split.js'
|
|
56
55
|
import keys from 'lodash-es/keys.js'
|
|
@@ -62,7 +61,6 @@ import genPm from 'wsemi/src/genPm.mjs'
|
|
|
62
61
|
import genIDSeq from 'wsemi/src/genIDSeq.mjs'
|
|
63
62
|
import isarr from 'wsemi/src/isarr.mjs'
|
|
64
63
|
import isearr from 'wsemi/src/isearr.mjs'
|
|
65
|
-
import isobj from 'wsemi/src/isobj.mjs'
|
|
66
64
|
import iseobj from 'wsemi/src/iseobj.mjs'
|
|
67
65
|
import isbol from 'wsemi/src/isbol.mjs'
|
|
68
66
|
import isnum from 'wsemi/src/isnum.mjs'
|
|
@@ -74,6 +72,7 @@ import pmQueue from 'wsemi/src/pmQueue.mjs'
|
|
|
74
72
|
import WAutoSequelize from 'w-auto-sequelize/src/WAutoSequelize.mjs'
|
|
75
73
|
import importModels from './importModels.mjs'
|
|
76
74
|
import _genModelsByTabs from './genModelsByTabs.mjs'
|
|
75
|
+
import cvFind, { getColKind, getColScale, normPk } from './cvFind.mjs'
|
|
77
76
|
|
|
78
77
|
|
|
79
78
|
//放置於全域宣告, 若使用useStable=true才可於當創建多實例時仍能全域控管
|
|
@@ -141,10 +140,6 @@ function WOrmReladb(opt = {}) {
|
|
|
141
140
|
}
|
|
142
141
|
|
|
143
142
|
|
|
144
|
-
//Op
|
|
145
|
-
let Op = Sequelize.Op
|
|
146
|
-
|
|
147
|
-
|
|
148
143
|
//ee, 採wsemi之evem(即eventemitter3), 其於'error'無監聽者時僅回傳false而不拋出,
|
|
149
144
|
//故本套件之操作行為不因呼叫端有無註冊監聽而改變; Node內建之EventEmitter具該拋出語義, 不可用
|
|
150
145
|
let ee = evem()
|
|
@@ -271,26 +266,16 @@ function WOrmReladb(opt = {}) {
|
|
|
271
266
|
|
|
272
267
|
|
|
273
268
|
/**
|
|
274
|
-
* 判定主鍵值是否有效
|
|
275
|
-
* 註: select
|
|
269
|
+
* 判定主鍵值是否有效(與主鍵欄型別無關之判定)
|
|
270
|
+
* 註: select以外之五函數對主鍵之認定一律以本函數與normPkOf為準,令selectByPk之[命中]與insert、save、del內對既有數據之認定一致
|
|
271
|
+
* 註: 有效即非空字串或有限數值(含0), new String與new Number取原始值; NaN、±Infinity、布林、物件等為無效(見cvFind.mjs之normPk)
|
|
276
272
|
*
|
|
277
273
|
* @ignore
|
|
278
274
|
* @param {*} v 輸入主鍵值
|
|
279
275
|
* @returns {Boolean} 回傳主鍵值是否有效布林值
|
|
280
276
|
*/
|
|
281
277
|
function isEffPk(v) {
|
|
282
|
-
|
|
283
|
-
//非空字串
|
|
284
|
-
if (isestr(v)) {
|
|
285
|
-
return true
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
//數值, 含0, 供整數型主鍵使用
|
|
289
|
-
if (isnum(v)) {
|
|
290
|
-
return true
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
return false
|
|
278
|
+
return normPk(v, 'any').kind !== 'invalid'
|
|
294
279
|
}
|
|
295
280
|
|
|
296
281
|
|
|
@@ -367,6 +352,80 @@ function WOrmReladb(opt = {}) {
|
|
|
367
352
|
}
|
|
368
353
|
|
|
369
354
|
|
|
355
|
+
/**
|
|
356
|
+
* 取cvFind所需之依賴物件
|
|
357
|
+
* 註: escape依方言產生字串常值(如mssql之N'...'), attrs供依欄位型別檢核條件之純量, dialect供判定方言能力,
|
|
358
|
+
* pk令主鍵欄之條件值依normPk正規化而與主鍵函數一致
|
|
359
|
+
*
|
|
360
|
+
* @ignore
|
|
361
|
+
* @param {Object} md 輸入資料表model物件
|
|
362
|
+
* @returns {Object} 回傳{escape, attrs, dialect, pk}
|
|
363
|
+
*/
|
|
364
|
+
function getFindCtx(md) {
|
|
365
|
+
return {
|
|
366
|
+
escape: (v) => md.sequelize.escape(v),
|
|
367
|
+
attrs: get(md, 'rawAttributes', {}),
|
|
368
|
+
dialect,
|
|
369
|
+
pk: opt.pk,
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* 檢查model之預設scope是否會使select與delAll之對象分歧
|
|
376
|
+
* 註: defaultScope帶limit或offset時, select依其order取前幾筆, 而sequelize之限量刪除不採order(sqlite為rowid IN子查詢),
|
|
377
|
+
* 兩者命中之數據不同而會刪錯列, 故delAll遇此類model即拒絕
|
|
378
|
+
*
|
|
379
|
+
* @ignore
|
|
380
|
+
* @param {Object} md 輸入資料表model物件
|
|
381
|
+
* @returns {undefined} 無回傳值
|
|
382
|
+
*/
|
|
383
|
+
function chkScopeForDelAll(md) {
|
|
384
|
+
let sc = get(md, '_scope', {})
|
|
385
|
+
if (get(sc, 'limit') !== undefined || get(sc, 'offset') !== undefined) {
|
|
386
|
+
throw new Error(`model [${opt.cl}] has defaultScope with limit or offset, delAll can not delete the same rows as select`)
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* 正規化各筆數據之主鍵值並就地寫回, 型別不符者整批拋出
|
|
393
|
+
* 註: 須於procPk之後、任何寫入之前一次完成; 已給主鍵而型別不符屬呼叫端未履行契約, 不以自動產生之主鍵取代
|
|
394
|
+
* 註: 正規化值寫回數據, 令寫入值與其後各函數之比對值一致(如字串類主鍵欄之123存為'123'), 事件之數據亦為實際寫入者
|
|
395
|
+
*
|
|
396
|
+
* @ignore
|
|
397
|
+
* @param {Object} md 輸入資料表model物件
|
|
398
|
+
* @param {Array} data 輸入已補齊主鍵之數據陣列
|
|
399
|
+
* @returns {undefined} 無回傳值
|
|
400
|
+
*/
|
|
401
|
+
function normPks(md, data) {
|
|
402
|
+
data.forEach((v, k) => {
|
|
403
|
+
let r = normPkOf(md, get(v, opt.pk))
|
|
404
|
+
if (r.kind !== 'ok') {
|
|
405
|
+
throw new Error(`invalid data[${k}].${opt.pk}[${get(v, opt.pk)}], type does not match pk column [${opt.pk}]`)
|
|
406
|
+
}
|
|
407
|
+
v[opt.pk] = r.v
|
|
408
|
+
})
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* 依model之主鍵欄型別正規化主鍵值
|
|
414
|
+
* 註: 規則見cvFind.mjs之normPk(與w-orm-mdb同一規則), 用於selectByPk、del、save、insert與insertBulk,
|
|
415
|
+
* 並與select、delAll之主鍵欄條件共用, 令各函數對主鍵之命中判定一致; 字串類主鍵欄之有限數字以String(v)處置,
|
|
416
|
+
* 整數類收安全整數與標準整數寫法之字串, DECIMAL之小數位不得多於scale, 型別不符者即規格之[主鍵值無效(型別不符)]而不送查詢
|
|
417
|
+
*
|
|
418
|
+
* @ignore
|
|
419
|
+
* @param {Object} md 輸入資料表model物件
|
|
420
|
+
* @param {*} v 輸入主鍵值
|
|
421
|
+
* @returns {Object} 回傳{kind,v}, kind為'ok'、'invalid'或'mismatch'
|
|
422
|
+
*/
|
|
423
|
+
function normPkOf(md, v) {
|
|
424
|
+
let attrs = get(md, 'rawAttributes', {})
|
|
425
|
+
return normPk(v, getColKind(attrs, opt.pk), getColScale(attrs, opt.pk))
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
|
|
370
429
|
/**
|
|
371
430
|
* 檢查並補齊單筆數據之主鍵
|
|
372
431
|
* autoGenPk為true時未帶有效主鍵者自動產生,為false時往外拋
|
|
@@ -521,77 +580,25 @@ function WOrmReladb(opt = {}) {
|
|
|
521
580
|
/**
|
|
522
581
|
* 查詢數據
|
|
523
582
|
*
|
|
583
|
+
* 註: find由cvFind轉譯且與delAll共用, 同一find於兩函數由同一SQL謂詞決定命中
|
|
584
|
+
* 註: 支援欄位等值({欄位:值}, 值為null時比對IS NULL)與$eq、$ne、$gt、$gte、$lt、$lte、$in、$nin、$not、$regex($options僅i)、$exists, 以及$and、$or、$nor
|
|
585
|
+
* 註: 不支援之運算子、非純量之值、與欄位型別不符之純量(如數值欄給'abc')一律reject並發出error事件, 不靜默忽略或改變語意
|
|
586
|
+
* 註: 主鍵欄之條件值依主鍵欄型別正規化而與selectByPk等一致(如字串類主鍵欄之{id:123}即{id:'123'}, 整數類主鍵欄之'12'即12), 型別不符或無效者reject
|
|
587
|
+
* 註: NULL依SQL三值邏輯, 故$ne、$nin、$not、$nor不含該欄為NULL之數據; $exists:false即IS NULL
|
|
588
|
+
* 註: $regex僅支援字面子字串(含未跳脫正規式元字元者reject, 可用反斜線跳脫), 給i時不分大小寫, 未給i時大小寫依資料庫定序(sqlite之LIKE與mssql預設定序皆不分)
|
|
589
|
+
* 註: 欄位值為陣列時視同$in, 與MongoDB之陣列比對不同
|
|
590
|
+
* 註: find未給或為空物件時回傳全部數據; find非物件時亦回傳全部數據(現況保留)
|
|
591
|
+
* 註: 恆回傳陣列, 無符合數據回傳空陣列
|
|
592
|
+
*
|
|
524
593
|
* @memberOf WOrmReladb
|
|
525
594
|
* @param {Object} [find={}] 輸入查詢條件物件
|
|
526
595
|
* @param {Object} [option={}] 輸入設定物件,預設為{}
|
|
527
596
|
* @param {Object} [option.instance=null] 輸入實例instance物件,預設為null
|
|
528
597
|
* @param {Object} [option.transaction=null] 輸入交易(transaction)物件,預設為null
|
|
529
|
-
* @returns {Promise} 回傳Promise,resolve
|
|
598
|
+
* @returns {Promise} 回傳Promise,resolve回傳數據陣列,reject回傳錯誤訊息
|
|
530
599
|
*/
|
|
531
600
|
async function select(find = {}, option = {}) {
|
|
532
601
|
|
|
533
|
-
function cvObj(o) {
|
|
534
|
-
let oNew = {}
|
|
535
|
-
each(o, (v, k) => {
|
|
536
|
-
let kNew = k
|
|
537
|
-
if (k.indexOf('$') >= 0) {
|
|
538
|
-
k = k.replace('$', '')
|
|
539
|
-
if (k === 'regex') {
|
|
540
|
-
kNew = Op.substring
|
|
541
|
-
}
|
|
542
|
-
else if (k === 'options') {
|
|
543
|
-
kNew = null
|
|
544
|
-
}
|
|
545
|
-
else if (k === 'nin') {
|
|
546
|
-
kNew = Op.notIn
|
|
547
|
-
}
|
|
548
|
-
else {
|
|
549
|
-
kNew = Op[k]
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
let vNew = v
|
|
553
|
-
if (isarr(v)) {
|
|
554
|
-
vNew = cvArray(v)
|
|
555
|
-
}
|
|
556
|
-
else if (isobj(v)) {
|
|
557
|
-
vNew = cvObj(v)
|
|
558
|
-
}
|
|
559
|
-
if (kNew !== null) {
|
|
560
|
-
oNew[kNew] = vNew
|
|
561
|
-
}
|
|
562
|
-
})
|
|
563
|
-
return oNew
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
function cvArray(o) {
|
|
567
|
-
let oNew = []
|
|
568
|
-
each(o, (v) => {
|
|
569
|
-
let vNew = v
|
|
570
|
-
if (isarr(v)) {
|
|
571
|
-
vNew = cvArray(v)
|
|
572
|
-
}
|
|
573
|
-
else if (isobj(v)) {
|
|
574
|
-
vNew = cvObj(v)
|
|
575
|
-
}
|
|
576
|
-
oNew.push(vNew)
|
|
577
|
-
})
|
|
578
|
-
return oNew
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
function cvFind(o) {
|
|
582
|
-
let oNew = cvObj(o)
|
|
583
|
-
return oNew
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
//find
|
|
587
|
-
if (!isobj(find)) {
|
|
588
|
-
find = {}
|
|
589
|
-
}
|
|
590
|
-
find = cloneDeep(find)
|
|
591
|
-
|
|
592
|
-
//useFind
|
|
593
|
-
let useFind = cvFind(find)
|
|
594
|
-
|
|
595
602
|
//instance
|
|
596
603
|
let instance = get(option, 'instance', null)
|
|
597
604
|
|
|
@@ -611,12 +618,17 @@ function WOrmReladb(opt = {}) {
|
|
|
611
618
|
|
|
612
619
|
//si
|
|
613
620
|
let si = instance
|
|
614
|
-
if (instance === null) {
|
|
615
|
-
si = await initSequelize()
|
|
616
|
-
}
|
|
617
621
|
|
|
618
622
|
try {
|
|
619
623
|
|
|
624
|
+
//check, 實例已關閉屬整批性錯誤, 於入口快速失敗
|
|
625
|
+
procClosed(instance)
|
|
626
|
+
|
|
627
|
+
//initSequelize, 內部自動初始化須在try內: 其例外(如驅動缺失)與si.err同屬整批性錯誤, 方能於reject前發出error事件, 已建構之sequelize亦由finally關閉
|
|
628
|
+
if (instance === null) {
|
|
629
|
+
si = await initSequelize()
|
|
630
|
+
}
|
|
631
|
+
|
|
620
632
|
//check, 連線或匯入models失敗影響本次操作之全部數據, 屬整批性錯誤
|
|
621
633
|
if (si.err) {
|
|
622
634
|
throw si.err
|
|
@@ -625,6 +637,9 @@ function WOrmReladb(opt = {}) {
|
|
|
625
637
|
//md
|
|
626
638
|
let md = si.mds[opt.cl]
|
|
627
639
|
|
|
640
|
+
//useFind, 與delAll共用cvFind, 條件不合法者於此拋錯而reject並發出error事件
|
|
641
|
+
let useFind = cvFind(find, getFindCtx(md))
|
|
642
|
+
|
|
628
643
|
//setting, raw令回傳純數據物件而不含資料庫內部欄位
|
|
629
644
|
let setting = {
|
|
630
645
|
where: useFind,
|
|
@@ -669,6 +684,8 @@ function WOrmReladb(opt = {}) {
|
|
|
669
684
|
*
|
|
670
685
|
* 註: 主鍵欄位取自opt.pk,預設為id,支援由呼叫端指定
|
|
671
686
|
* 註: 主鍵未命中或主鍵值無效皆回傳null而不reject,[命中]之判定基準與insert、save、del內對既有數據之認定一致
|
|
687
|
+
* 註: 主鍵值依主鍵欄型別正規化後查詢: 字串類主鍵欄之有限數字以String(v)處置(selectByPk(123)即查'123'), 整數類主鍵欄之標準整數寫法字串轉為數值;
|
|
688
|
+
* 型別不符(整數類主鍵欄給'012'、12.4、'abc'等)亦屬主鍵值無效而回傳null
|
|
672
689
|
* 註: 本函數不得有副作用,故不創建資料表
|
|
673
690
|
*
|
|
674
691
|
* @memberOf WOrmReladb
|
|
@@ -713,15 +730,17 @@ function WOrmReladb(opt = {}) {
|
|
|
713
730
|
|
|
714
731
|
//si
|
|
715
732
|
let si = instance
|
|
716
|
-
if (instance === null) {
|
|
717
|
-
si = await initSequelize()
|
|
718
|
-
}
|
|
719
733
|
|
|
720
734
|
try {
|
|
721
735
|
|
|
722
736
|
//check, 實例已關閉屬整批性錯誤, 於入口快速失敗
|
|
723
737
|
procClosed(instance)
|
|
724
738
|
|
|
739
|
+
//initSequelize, 內部自動初始化須在try內: 其例外(如驅動缺失)與si.err同屬整批性錯誤, 方能於reject前發出error事件, 已建構之sequelize亦由finally關閉
|
|
740
|
+
if (instance === null) {
|
|
741
|
+
si = await initSequelize()
|
|
742
|
+
}
|
|
743
|
+
|
|
725
744
|
//check
|
|
726
745
|
if (si.err) {
|
|
727
746
|
throw si.err
|
|
@@ -730,25 +749,34 @@ function WOrmReladb(opt = {}) {
|
|
|
730
749
|
//md
|
|
731
750
|
let md = si.mds[opt.cl]
|
|
732
751
|
|
|
733
|
-
//
|
|
734
|
-
let
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
}
|
|
738
|
-
if (transaction !== null) {
|
|
739
|
-
setting.transaction = transaction
|
|
752
|
+
//normPkOf, 依主鍵欄型別正規化, 型別不符即主鍵值無效而回null且不送查詢(送出時兩方言皆會把整數欄之'012'轉為12而命中)
|
|
753
|
+
let r = normPkOf(md, pk)
|
|
754
|
+
if (r.kind !== 'ok') {
|
|
755
|
+
res = null
|
|
740
756
|
}
|
|
757
|
+
else {
|
|
741
758
|
|
|
742
|
-
|
|
743
|
-
|
|
759
|
+
//setting
|
|
760
|
+
let setting = {
|
|
761
|
+
where: { [opt.pk]: r.v },
|
|
762
|
+
raw: true,
|
|
763
|
+
}
|
|
764
|
+
if (transaction !== null) {
|
|
765
|
+
setting.transaction = transaction
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
//findOne
|
|
769
|
+
let v = await md.findOne(setting)
|
|
770
|
+
|
|
771
|
+
//check, 判定基準與insert、save、del內對既有數據之認定一致
|
|
772
|
+
if (iseobj(v)) {
|
|
773
|
+
res = v
|
|
774
|
+
}
|
|
775
|
+
else {
|
|
776
|
+
//不存在主鍵, 回傳null
|
|
777
|
+
res = null
|
|
778
|
+
}
|
|
744
779
|
|
|
745
|
-
//check, 判定基準與insert、save、del內對既有數據之認定一致
|
|
746
|
-
if (iseobj(v)) {
|
|
747
|
-
res = v
|
|
748
|
-
}
|
|
749
|
-
else {
|
|
750
|
-
//不存在主鍵, 回傳null
|
|
751
|
-
res = null
|
|
752
780
|
}
|
|
753
781
|
|
|
754
782
|
}
|
|
@@ -783,6 +811,7 @@ function WOrmReladb(opt = {}) {
|
|
|
783
811
|
* 註: n為輸入筆數即本次嘗試插入之基準,nInserted為實際插入筆數,全數已存在而nInserted為0屬正常結果
|
|
784
812
|
* 註: 同批含重複主鍵時僅首筆計入nInserted,其餘視為已存在
|
|
785
813
|
* 註: opt.autoGenPk為true(預設)時未帶有效主鍵者自動產生,為false時未帶有效主鍵即reject且同批皆不寫入
|
|
814
|
+
* 註: 主鍵值依主鍵欄型別正規化後寫入(字串類主鍵欄之123存為'123');型別不符(整數類主鍵欄給'012'等)即reject且同批皆不寫入,不以自動產生之主鍵取代
|
|
786
815
|
* 註: option.returnList開啟時改回與輸入等長且保序之逐筆結果陣列[{n,nInserted,ok}],
|
|
787
816
|
* 聚合計數只答得出[有幾筆是新的]而答不出[是哪幾筆],而後者正是去重之產出物;
|
|
788
817
|
* 逐筆元素之n與ok恆為1,資訊由nInserted承載,不變式為
|
|
@@ -835,15 +864,17 @@ function WOrmReladb(opt = {}) {
|
|
|
835
864
|
|
|
836
865
|
//si
|
|
837
866
|
let si = instance
|
|
838
|
-
if (instance === null) {
|
|
839
|
-
si = await initSequelize()
|
|
840
|
-
}
|
|
841
867
|
|
|
842
868
|
try {
|
|
843
869
|
|
|
844
870
|
//check, 實例已關閉屬整批性錯誤, 於入口快速失敗
|
|
845
871
|
procClosed(instance)
|
|
846
872
|
|
|
873
|
+
//initSequelize, 內部自動初始化須在try內: 其例外(如驅動缺失)與si.err同屬整批性錯誤, 方能於reject前發出error事件, 已建構之sequelize亦由finally關閉
|
|
874
|
+
if (instance === null) {
|
|
875
|
+
si = await initSequelize()
|
|
876
|
+
}
|
|
877
|
+
|
|
847
878
|
//check
|
|
848
879
|
if (si.err) {
|
|
849
880
|
throw si.err
|
|
@@ -862,6 +893,9 @@ function WOrmReladb(opt = {}) {
|
|
|
862
893
|
return procPk(md, v, k)
|
|
863
894
|
})
|
|
864
895
|
|
|
896
|
+
//normPks, 主鍵值依主鍵欄型別正規化後寫回, 型別不符者整批reject且不寫入任何一筆, 令insert對既有數據之認定與selectByPk一致
|
|
897
|
+
normPks(md, data)
|
|
898
|
+
|
|
865
899
|
//nAll, n之基準為輸入筆數
|
|
866
900
|
let nAll = size(data)
|
|
867
901
|
|
|
@@ -954,6 +988,7 @@ function WOrmReladb(opt = {}) {
|
|
|
954
988
|
* 令呼叫端得與insert共用同一段結果處理程式碼
|
|
955
989
|
* 註: 不提供逐筆結果,故不出現ok為0與err;需要逐筆處置者改用insert
|
|
956
990
|
* 註: opt.autoGenPk為true(預設)時未帶有效主鍵者自動產生,為false時未帶有效主鍵即reject且同批皆不寫入
|
|
991
|
+
* 註: 主鍵值依主鍵欄型別正規化後寫入(字串類主鍵欄之123存為'123');型別不符(整數類主鍵欄給'012'等)即reject且同批皆不寫入
|
|
957
992
|
* 註: [全有全無]為獨立於T7之額外要求——T7僅保證每筆之[檢查主鍵不存在]與[寫入]為原子,不保證整批。
|
|
958
993
|
* mssql因綁定參數數量上限會由驅動層自動拆為多語句送出,實測1000筆之批次於末筆撞主鍵時已有946筆落盤,
|
|
959
994
|
* 故一律以交易包覆並於失敗時回滾;呼叫端已給transaction時改以巢狀交易(SAVEPOINT)包覆,
|
|
@@ -999,15 +1034,17 @@ function WOrmReladb(opt = {}) {
|
|
|
999
1034
|
|
|
1000
1035
|
//si
|
|
1001
1036
|
let si = instance
|
|
1002
|
-
if (instance === null) {
|
|
1003
|
-
si = await initSequelize()
|
|
1004
|
-
}
|
|
1005
1037
|
|
|
1006
1038
|
try {
|
|
1007
1039
|
|
|
1008
1040
|
//check, 實例已關閉屬整批性錯誤, 於入口快速失敗
|
|
1009
1041
|
procClosed(instance)
|
|
1010
1042
|
|
|
1043
|
+
//initSequelize, 內部自動初始化須在try內: 其例外(如驅動缺失)與si.err同屬整批性錯誤, 方能於reject前發出error事件, 已建構之sequelize亦由finally關閉
|
|
1044
|
+
if (instance === null) {
|
|
1045
|
+
si = await initSequelize()
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1011
1048
|
//check
|
|
1012
1049
|
if (si.err) {
|
|
1013
1050
|
throw si.err
|
|
@@ -1026,6 +1063,9 @@ function WOrmReladb(opt = {}) {
|
|
|
1026
1063
|
return procPk(md, v, k)
|
|
1027
1064
|
})
|
|
1028
1065
|
|
|
1066
|
+
//normPks, 主鍵值依主鍵欄型別正規化後寫回, 型別不符者整批reject且不寫入任何一筆
|
|
1067
|
+
normPks(md, data)
|
|
1068
|
+
|
|
1029
1069
|
//nAll, n之基準為輸入筆數
|
|
1030
1070
|
let nAll = size(data)
|
|
1031
1071
|
|
|
@@ -1284,6 +1324,7 @@ function WOrmReladb(opt = {}) {
|
|
|
1284
1324
|
* 故只給部份欄位且該些欄位值皆與現值相同時,合併結果等於現值,nModified為0
|
|
1285
1325
|
* 註: 本筆失敗不中斷整批,該筆以ok為0並附err回報
|
|
1286
1326
|
* 註: opt.autoGenPk為true(預設)時未帶有效主鍵者自動產生,為false時未帶有效主鍵即reject且同批皆不寫入
|
|
1327
|
+
* 註: 主鍵值依主鍵欄型別正規化(字串類主鍵欄之123即'123');型別不符(整數類主鍵欄給'012'等)屬呼叫端未履行契約,整批reject且同批皆不寫入
|
|
1287
1328
|
*
|
|
1288
1329
|
* @memberOf WOrmReladb
|
|
1289
1330
|
* @param {Object|Array} data 輸入數據物件或陣列
|
|
@@ -1325,15 +1366,17 @@ function WOrmReladb(opt = {}) {
|
|
|
1325
1366
|
|
|
1326
1367
|
//si
|
|
1327
1368
|
let si = instance
|
|
1328
|
-
if (instance === null) {
|
|
1329
|
-
si = await initSequelize()
|
|
1330
|
-
}
|
|
1331
1369
|
|
|
1332
1370
|
try {
|
|
1333
1371
|
|
|
1334
1372
|
//check, 實例已關閉屬整批性錯誤, 於入口快速失敗
|
|
1335
1373
|
procClosed(instance)
|
|
1336
1374
|
|
|
1375
|
+
//initSequelize, 內部自動初始化須在try內: 其例外(如驅動缺失)與si.err同屬整批性錯誤, 方能於reject前發出error事件, 已建構之sequelize亦由finally關閉
|
|
1376
|
+
if (instance === null) {
|
|
1377
|
+
si = await initSequelize()
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1337
1380
|
//check
|
|
1338
1381
|
if (si.err) {
|
|
1339
1382
|
throw si.err
|
|
@@ -1352,6 +1395,9 @@ function WOrmReladb(opt = {}) {
|
|
|
1352
1395
|
return procPk(md, v, k)
|
|
1353
1396
|
})
|
|
1354
1397
|
|
|
1398
|
+
//normPks, 主鍵值依主鍵欄型別正規化後寫回, 型別不符者整批reject且不寫入任何一筆
|
|
1399
|
+
normPks(md, data)
|
|
1400
|
+
|
|
1355
1401
|
//ks, model之欄位名, 供合併後比對時濾除非欄位之鍵
|
|
1356
1402
|
let ks = keys(get(md, 'rawAttributes', {}))
|
|
1357
1403
|
|
|
@@ -1393,7 +1439,8 @@ function WOrmReladb(opt = {}) {
|
|
|
1393
1439
|
* 註: 回傳陣列恆與輸入等長,各筆之n與nDeleted皆為主鍵命中筆數,值為0或1,未命中為0且屬正常結果
|
|
1394
1440
|
* 註: 判斷某筆是否真的被刪除一律以nDeleted為準
|
|
1395
1441
|
* 註: 未帶有效主鍵者為該筆之輸入問題,回ok為0與err且不送查詢條件(以免無效值被轉為null而誤中其他數據),
|
|
1396
|
-
* 不中斷其餘筆數,以此與[主鍵未命中]之ok為1
|
|
1442
|
+
* 不中斷其餘筆數,以此與[主鍵未命中]之ok為1區辨;主鍵值與主鍵欄型別不符者(整數類主鍵欄給'012'等)亦同
|
|
1443
|
+
* 註: 主鍵值依主鍵欄型別正規化後刪除(字串類主鍵欄之123即'123'),正規化值寫回該筆數據
|
|
1397
1444
|
* 註: 本函數不受opt.autoGenPk影響,於任一設定下皆不補值
|
|
1398
1445
|
*
|
|
1399
1446
|
* @memberOf WOrmReladb
|
|
@@ -1432,15 +1479,17 @@ function WOrmReladb(opt = {}) {
|
|
|
1432
1479
|
|
|
1433
1480
|
//si
|
|
1434
1481
|
let si = instance
|
|
1435
|
-
if (instance === null) {
|
|
1436
|
-
si = await initSequelize()
|
|
1437
|
-
}
|
|
1438
1482
|
|
|
1439
1483
|
try {
|
|
1440
1484
|
|
|
1441
1485
|
//check, 實例已關閉屬整批性錯誤, 於入口快速失敗
|
|
1442
1486
|
procClosed(instance)
|
|
1443
1487
|
|
|
1488
|
+
//initSequelize, 內部自動初始化須在try內: 其例外(如驅動缺失)與si.err同屬整批性錯誤, 方能於reject前發出error事件, 已建構之sequelize亦由finally關閉
|
|
1489
|
+
if (instance === null) {
|
|
1490
|
+
si = await initSequelize()
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1444
1493
|
//check
|
|
1445
1494
|
if (si.err) {
|
|
1446
1495
|
throw si.err
|
|
@@ -1480,9 +1529,30 @@ function WOrmReladb(opt = {}) {
|
|
|
1480
1529
|
return rest
|
|
1481
1530
|
}
|
|
1482
1531
|
|
|
1532
|
+
//normPkOf, 主鍵值與主鍵欄型別不符亦屬未帶有效主鍵, 不送查詢(送出時兩方言皆會把整數欄之'012'轉為12而誤刪)
|
|
1533
|
+
let r = normPkOf(md, pkv)
|
|
1534
|
+
if (r.kind !== 'ok') {
|
|
1535
|
+
|
|
1536
|
+
//rest
|
|
1537
|
+
rest = {
|
|
1538
|
+
n: 0,
|
|
1539
|
+
nDeleted: 0,
|
|
1540
|
+
ok: 0,
|
|
1541
|
+
err: `invalid ${opt.pk}[${pkv}], type does not match pk column`,
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
//emit
|
|
1545
|
+
emitError('del', [v], rest.err)
|
|
1546
|
+
|
|
1547
|
+
return rest
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
//寫回正規化值, 令事件之數據與實際送出者一致
|
|
1551
|
+
v[opt.pk] = r.v
|
|
1552
|
+
|
|
1483
1553
|
//setting
|
|
1484
1554
|
let setting = {
|
|
1485
|
-
where: { [opt.pk]:
|
|
1555
|
+
where: { [opt.pk]: r.v },
|
|
1486
1556
|
}
|
|
1487
1557
|
if (transaction !== null) {
|
|
1488
1558
|
setting.transaction = transaction //destroy的說明寫不需transaction但實際需要 (2020/10/07)
|
|
@@ -1558,6 +1628,9 @@ function WOrmReladb(opt = {}) {
|
|
|
1558
1628
|
*
|
|
1559
1629
|
* 註: n與nDeleted皆為實際刪除筆數,兩者恆相等,n不得取全表筆數
|
|
1560
1630
|
* 註: find未給或為空物件時刪除全部數據;條件無命中時回{n:0,nDeleted:0,ok:1},不視為錯誤
|
|
1631
|
+
* 註: find由cvFind轉譯且與select共用,刪除之數據即select(find)命中之數據;支援之條件與限制同select
|
|
1632
|
+
* 註: 不支援之運算子、非純量之值、與欄位型別不符之純量一律reject並發出error事件,不刪除任何數據;主鍵欄之條件值依主鍵欄型別正規化,同select
|
|
1633
|
+
* 註: find非物件(null、陣列、字串、數字)時刪除全部數據,此為現況保留,系列規格另案處理
|
|
1561
1634
|
*
|
|
1562
1635
|
* @memberOf WOrmReladb
|
|
1563
1636
|
* @param {Object} [find={}] 輸入刪除條件物件,不給予find則代表刪除全部數據
|
|
@@ -1568,12 +1641,6 @@ function WOrmReladb(opt = {}) {
|
|
|
1568
1641
|
*/
|
|
1569
1642
|
async function delAll(find = {}, option = {}) {
|
|
1570
1643
|
|
|
1571
|
-
//find
|
|
1572
|
-
if (!isobj(find)) {
|
|
1573
|
-
find = {}
|
|
1574
|
-
}
|
|
1575
|
-
find = cloneDeep(find)
|
|
1576
|
-
|
|
1577
1644
|
//instance
|
|
1578
1645
|
let instance = get(option, 'instance', null)
|
|
1579
1646
|
|
|
@@ -1593,15 +1660,17 @@ function WOrmReladb(opt = {}) {
|
|
|
1593
1660
|
|
|
1594
1661
|
//si
|
|
1595
1662
|
let si = instance
|
|
1596
|
-
if (instance === null) {
|
|
1597
|
-
si = await initSequelize()
|
|
1598
|
-
}
|
|
1599
1663
|
|
|
1600
1664
|
try {
|
|
1601
1665
|
|
|
1602
1666
|
//check, 實例已關閉屬整批性錯誤, 於入口快速失敗
|
|
1603
1667
|
procClosed(instance)
|
|
1604
1668
|
|
|
1669
|
+
//initSequelize, 內部自動初始化須在try內: 其例外(如驅動缺失)與si.err同屬整批性錯誤, 方能於reject前發出error事件, 已建構之sequelize亦由finally關閉
|
|
1670
|
+
if (instance === null) {
|
|
1671
|
+
si = await initSequelize()
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1605
1674
|
//check
|
|
1606
1675
|
if (si.err) {
|
|
1607
1676
|
throw si.err
|
|
@@ -1610,9 +1679,15 @@ function WOrmReladb(opt = {}) {
|
|
|
1610
1679
|
//md
|
|
1611
1680
|
let md = si.mds[opt.cl]
|
|
1612
1681
|
|
|
1682
|
+
//useFind, 與select共用cvFind, 令刪除之數據即select命中之數據; 條件不合法者於此拋錯而不刪除任何數據
|
|
1683
|
+
let useFind = cvFind(find, getFindCtx(md))
|
|
1684
|
+
|
|
1685
|
+
//chkScopeForDelAll, model之預設scope會使刪除對象與select分歧者拒絕
|
|
1686
|
+
chkScopeForDelAll(md)
|
|
1687
|
+
|
|
1613
1688
|
//setting
|
|
1614
1689
|
let setting = {
|
|
1615
|
-
where:
|
|
1690
|
+
where: useFind,
|
|
1616
1691
|
}
|
|
1617
1692
|
if (transaction !== null) {
|
|
1618
1693
|
setting.transaction = transaction //destroy的說明寫不需transaction但實際需要 (2020/10/07)
|
|
@@ -1822,7 +1897,7 @@ export default WOrmReladb
|
|
|
1822
1897
|
<br class="clear">
|
|
1823
1898
|
|
|
1824
1899
|
<footer>
|
|
1825
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on
|
|
1900
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Oct 16 2026 14:32:44 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
1826
1901
|
</footer>
|
|
1827
1902
|
|
|
1828
1903
|
<script>prettyPrint();</script>
|