w-orm-reladb 1.1.9 → 1.1.10

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/docs/global.html CHANGED
@@ -141,15 +141,16 @@
141
141
 
142
142
  <dt class="tag-description">Description:</dt>
143
143
  <dd class="tag-description"><ul class="dummy"><li><p>將查詢條件轉為sequelize之where, 供select與delAll共用, 令同一find於兩函數由同一SQL謂詞決定命中</p>
144
- <p>註: 支援欄位等值與$eq、$ne、$gt、$gte、$lt、$lte、$in、$nin、$not、$regex($options僅i)、$exists, 以及$and、$or、$nor
145
- 註: 不支援之運算子、非純量之值、與欄位型別不符之純量一律拋錯, 不得交sequelize之型別stringify(見本檔之chkScalar)
146
- 註: NULL依SQL三值邏輯; $regex僅支援字面子字串; 非物件之find回{}(即全部), 此為現況保留</p></li></ul></dd>
144
+ <p>註: 第一步經chkFindShape(wsemi之cvOrmFind)依系列白名單檢核並取複本, 其後只走訪複本; 白名單: 欄位等值{欄:純量|null}、
145
+ $eq $ne $gt $gte $lt $lte(純量)、$in $nin(純量陣列)、$and $or(條件物件之非空陣列); 其餘(含$not $nor $regex $options $exists、RegExp、Symbol鍵、陣列值)一律拋錯
146
+ 註: 未給、undefined或{}回傳{}(全部); 其餘非條件物件(null、陣列、字串、數值等)拋錯, 不再視為{}
147
+ 註: 與欄位型別不符之純量、不存在之欄一律拋錯, 不得交sequelize之型別stringify(見本檔之chkScalar); NULL依SQL三值邏輯</p></li></ul></dd>
147
148
 
148
149
 
149
150
 
150
151
  <dt class="tag-source">Source:</dt>
151
152
  <dd class="tag-source"><ul class="dummy"><li>
152
- <a href="cvFind.mjs.html">cvFind.mjs</a>, <a href="cvFind.mjs.html#line1001">line 1001</a>
153
+ <a href="cvFind.mjs.html">cvFind.mjs</a>, <a href="cvFind.mjs.html#line730">line 730</a>
153
154
  </li></ul></dd>
154
155
 
155
156
 
@@ -306,6 +307,8 @@
306
307
 
307
308
  <td class="attributes">
308
309
 
310
+ &lt;optional><br>
311
+
309
312
 
310
313
 
311
314
 
@@ -315,7 +318,7 @@
315
318
 
316
319
 
317
320
 
318
- <td class="description last"><p>輸入依方言將字串轉為SQL字串常值之函數, 通常為sequelize實例之escape</p></td>
321
+ <td class="description last"><p>已不使用(原供$regex之LIKE字面常值; 第33項批1移除$regex), 保留接受以相容既有呼叫端</p></td>
319
322
  </tr>
320
323
 
321
324
 
@@ -383,7 +386,7 @@
383
386
 
384
387
 
385
388
 
386
- <td class="description last"><p>輸入資料庫種類字串, 供判定方言能力(如sqlite之LOWER僅折疊ASCII)</p></td>
389
+ <td class="description last"><p>已不使用(原供判定sqlite之LOWER僅折疊ASCII), 保留接受以相容既有呼叫端</p></td>
387
390
  </tr>
388
391
 
389
392
 
@@ -527,7 +530,7 @@
527
530
 
528
531
  <dt class="tag-source">Source:</dt>
529
532
  <dd class="tag-source"><ul class="dummy"><li>
530
- <a href="cvFind.mjs.html">cvFind.mjs</a>, <a href="cvFind.mjs.html#line197">line 197</a>
533
+ <a href="cvFind.mjs.html">cvFind.mjs</a>, <a href="cvFind.mjs.html#line155">line 155</a>
531
534
  </li></ul></dd>
532
535
 
533
536
 
@@ -709,7 +712,7 @@
709
712
 
710
713
  <dt class="tag-source">Source:</dt>
711
714
  <dd class="tag-source"><ul class="dummy"><li>
712
- <a href="cvFind.mjs.html">cvFind.mjs</a>, <a href="cvFind.mjs.html#line375">line 375</a>
715
+ <a href="cvFind.mjs.html">cvFind.mjs</a>, <a href="cvFind.mjs.html#line333">line 333</a>
713
716
  </li></ul></dd>
714
717
 
715
718
 
@@ -1294,7 +1297,7 @@
1294
1297
 
1295
1298
  <dt class="tag-source">Source:</dt>
1296
1299
  <dd class="tag-source"><ul class="dummy"><li>
1297
- <a href="cvFind.mjs.html">cvFind.mjs</a>, <a href="cvFind.mjs.html#line397">line 397</a>
1300
+ <a href="cvFind.mjs.html">cvFind.mjs</a>, <a href="cvFind.mjs.html#line355">line 355</a>
1298
1301
  </li></ul></dd>
1299
1302
 
1300
1303
 
@@ -1485,7 +1488,7 @@ DECIMAL主鍵欄之值小數位多於scale者寫入時會被四捨五入而改
1485
1488
 
1486
1489
  <dt class="tag-source">Source:</dt>
1487
1490
  <dd class="tag-source"><ul class="dummy"><li>
1488
- <a href="cvFind.mjs.html">cvFind.mjs</a>, <a href="cvFind.mjs.html#line490">line 490</a>
1491
+ <a href="cvFind.mjs.html">cvFind.mjs</a>, <a href="cvFind.mjs.html#line448">line 448</a>
1489
1492
  </li></ul></dd>
1490
1493
 
1491
1494
 
@@ -1737,7 +1740,7 @@ DECIMAL主鍵欄之值小數位多於scale者寫入時會被四捨五入而改
1737
1740
  <br class="clear">
1738
1741
 
1739
1742
  <footer>
1740
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Oct 16 2026 19:47:28 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1743
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Mon Oct 19 2026 18:54:43 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1741
1744
  </footer>
1742
1745
 
1743
1746
  <script>prettyPrint();</script>
@@ -242,7 +242,7 @@ export default importModels
242
242
  <br class="clear">
243
243
 
244
244
  <footer>
245
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Oct 16 2026 19:47:28 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
245
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Mon Oct 19 2026 18:54:43 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
246
246
  </footer>
247
247
 
248
248
  <script>prettyPrint();</script>
package/docs/index.html CHANGED
@@ -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 Fri Oct 16 2026 19:47:28 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 Oct 19 2026 18:54:43 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
75
75
  </footer>
76
76
 
77
77
  <script>prettyPrint();</script>
@@ -129,7 +129,7 @@ async function testCommit() {
129
129
 
130
130
 
131
131
  //select all
132
- let ssBeforeCommit = await w.select(null, connState)
132
+ let ssBeforeCommit = await w.select({}, connState)
133
133
  console.log('select all (before commit)', ssBeforeCommit) //此時select可查到暫時有效的數據
134
134
  // => [
135
135
  // { id: 'id-peter', name: 'peter(modify)', value: 123 },
@@ -129,7 +129,7 @@ async function testRollback() {
129
129
 
130
130
 
131
131
  //select all
132
- let ssBeforeRollback = await w.select(null, connState)
132
+ let ssBeforeRollback = await w.select({}, connState)
133
133
  console.log('select all (before rollback)', ssBeforeRollback) //此時select可查到暫時有效的數據
134
134
  // => [
135
135
  // { id: 'id-peter', name: 'peter(modify)', value: 123 },
package/g-mssql.mjs CHANGED
@@ -133,9 +133,9 @@ async function test() {
133
133
  console.log('select by $or, $and, $ne, $in, $nin', spc)
134
134
 
135
135
 
136
- //select by regex
137
- let sr = await w.select({ name: { $regex: 'PeT', $options: 'i' } })
138
- console.log('selectReg', sr)
136
+ //select by equality (there is no pattern matching: filter in memory for substrings)
137
+ let sr = await w.select({ name: 'peter(modify)' })
138
+ console.log('selectEq', sr)
139
139
 
140
140
 
141
141
  //del
@@ -189,7 +189,7 @@ test()
189
189
  // { id: 'id-rosemary', name: 'rosemary(modify)', value: 123.456 },
190
190
  // { id: '{random id}', name: 'kettle', value: 456 }
191
191
  // ]
192
- // selectReg [
192
+ // selectEq [
193
193
  // { id: 'id-peter', name: 'peter(modify)', value: 123 }
194
194
  // ]
195
195
  // change del
@@ -137,7 +137,7 @@
137
137
 
138
138
 
139
139
  // //select all
140
- // let ssBeforeCommit = await w.select(null, connState)
140
+ // let ssBeforeCommit = await w.select({}, connState)
141
141
  // console.log('select all (before commit)', ssBeforeCommit) //此時select可查到暫時有效的數據
142
142
  // // => [
143
143
  // // { id: 'id-peter', name: 'peter(modify)', value: 123 },
@@ -148,9 +148,9 @@ async function test() {
148
148
  console.log('select by $or, $and, $ne, $in, $nin', spc)
149
149
 
150
150
 
151
- //select by regex
152
- let sr = await w.select({ name: { $regex: 'PeT', $options: 'i' } })
153
- console.log('selectReg', sr)
151
+ //select by equality (there is no pattern matching: filter in memory for substrings)
152
+ let sr = await w.select({ name: 'peter(modify)' })
153
+ console.log('selectEq', sr)
154
154
 
155
155
 
156
156
  //del
@@ -204,7 +204,7 @@ test()
204
204
  // { id: 'id-rosemary', name: 'rosemary(modify)', value: 123.456 },
205
205
  // { id: '{random id}', name: 'kettle', value: 456 }
206
206
  // ]
207
- // selectReg [
207
+ // selectEq [
208
208
  // { id: 'id-peter', name: 'peter(modify)', value: 123 }
209
209
  // ]
210
210
  // change del
@@ -136,7 +136,7 @@ async function testCommit() {
136
136
 
137
137
 
138
138
  //select all
139
- let ssBeforeCommit = await w.select(null, connState)
139
+ let ssBeforeCommit = await w.select({}, connState)
140
140
  console.log('select all (before commit)', ssBeforeCommit) //此時select可查到暫時有效的數據
141
141
  // => [
142
142
  // { id: 'id-peter', name: 'peter(modify)', value: 123 },
@@ -136,7 +136,7 @@ async function testRollback() {
136
136
 
137
137
 
138
138
  //select all
139
- let ssBeforeRollback = await w.select(null, connState)
139
+ let ssBeforeRollback = await w.select({}, connState)
140
140
  console.log('select all (before rollback)', ssBeforeRollback) //此時select可查到暫時有效的數據
141
141
  // => [
142
142
  // { id: 'id-peter', name: 'peter(modify)', value: 123 },
package/g-sqlite.mjs CHANGED
@@ -141,9 +141,9 @@ async function test() {
141
141
  console.log('select by $or, $and, $ne, $in, $nin', spc)
142
142
 
143
143
 
144
- //select by regex
145
- let sr = await w.select({ name: { $regex: 'PeT', $options: 'i' } })
146
- console.log('selectReg', sr)
144
+ //select by equality (there is no pattern matching: filter in memory for substrings)
145
+ let sr = await w.select({ name: 'peter(modify)' })
146
+ console.log('selectEq', sr)
147
147
 
148
148
 
149
149
  //del
@@ -197,7 +197,7 @@ test()
197
197
  // { id: 'id-rosemary', name: 'rosemary(modify)', value: 123.456 },
198
198
  // { id: '{random id}', name: 'kettle', value: 456 }
199
199
  // ]
200
- // selectReg [
200
+ // selectEq [
201
201
  // { id: 'id-peter', name: 'peter(modify)', value: 123 }
202
202
  // ]
203
203
  // change del
@@ -0,0 +1,50 @@
1
+ /* jshint indent: 1 */
2
+ module.exports = function(sequelize, DataTypes) {
3
+ return sequelize.define('tfind', {
4
+ 'id': {
5
+ type: DataTypes.STRING,
6
+ allowNull: false,
7
+ primaryKey: true,
8
+ autoIncrement: false,
9
+ comment: null
10
+ },
11
+ 'name': {
12
+ type: DataTypes.STRING,
13
+ allowNull: true,
14
+ autoIncrement: false,
15
+ comment: null
16
+ },
17
+ 'age': {
18
+ type: DataTypes.INTEGER,
19
+ allowNull: true,
20
+ autoIncrement: false,
21
+ comment: null
22
+ },
23
+ 'g': {
24
+ type: DataTypes.STRING,
25
+ allowNull: true,
26
+ autoIncrement: false,
27
+ comment: null
28
+ },
29
+ 't': {
30
+ type: DataTypes.STRING,
31
+ allowNull: true,
32
+ autoIncrement: false,
33
+ comment: null
34
+ },
35
+ 'flag': {
36
+ type: DataTypes.BOOLEAN,
37
+ allowNull: true,
38
+ autoIncrement: false,
39
+ comment: null
40
+ },
41
+ 'd': {
42
+ type: DataTypes.DATE,
43
+ allowNull: true,
44
+ autoIncrement: false,
45
+ comment: null
46
+ }
47
+ }, {
48
+ tableName: 'tfind'
49
+ });
50
+ };
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "w-orm-reladb",
3
- "version": "1.1.9",
3
+ "version": "1.1.10",
4
4
  "main": "dist/w-orm-reladb.umd.js",
5
5
  "dependencies": {
6
6
  "json5": "^2.2.3",
7
7
  "sqlite3": "^6.0.1",
8
8
  "tedious": "^19.2.2",
9
9
  "w-auto-sequelize": "^1.0.48",
10
- "wsemi": "^1.9.16"
10
+ "wsemi": "^1.9.20"
11
11
  },
12
12
  "dependenciesTemp": {
13
13
  "@journeyapps/sqlcipher": "^5.3.1",
@@ -25,7 +25,7 @@ import pmQueue from 'wsemi/src/pmQueue.mjs'
25
25
  import WAutoSequelize from 'w-auto-sequelize/src/WAutoSequelize.mjs'
26
26
  import importModels from './importModels.mjs'
27
27
  import _genModelsByTabs from './genModelsByTabs.mjs'
28
- import cvFind, { getColKind, getColScale, normPk } from './cvFind.mjs'
28
+ import cvFind, { getColKind, getColScale, normPk, chkFindShape } from './cvFind.mjs'
29
29
 
30
30
 
31
31
  //放置於全域宣告, 若使用useStable=true才可於當創建多實例時仍能全域控管
@@ -307,18 +307,15 @@ function WOrmReladb(opt = {}) {
307
307
 
308
308
  /**
309
309
  * 取cvFind所需之依賴物件
310
- * 註: escape依方言產生字串常值(如mssql之N'...'), attrs供依欄位型別檢核條件之純量, dialect供判定方言能力,
311
- * pk令主鍵欄之條件值依normPk正規化而與主鍵函數一致
310
+ * 註: attrs供欄名解析(嚴格鍵)與依欄位型別檢核條件之純量, pk令主鍵欄之條件值依normPk正規化而與主鍵函數一致
312
311
  *
313
312
  * @ignore
314
313
  * @param {Object} md 輸入資料表model物件
315
- * @returns {Object} 回傳{escape, attrs, dialect, pk}
314
+ * @returns {Object} 回傳{attrs, pk}
316
315
  */
317
316
  function getFindCtx(md) {
318
317
  return {
319
- escape: (v) => md.sequelize.escape(v),
320
318
  attrs: get(md, 'rawAttributes', {}),
321
- dialect,
322
319
  pk: opt.pk,
323
320
  }
324
321
  }
@@ -556,18 +553,25 @@ function WOrmReladb(opt = {}) {
556
553
  /**
557
554
  * 查詢數據
558
555
  *
559
- * 註: find由cvFind轉譯且與delAll共用, 同一find於兩函數由同一SQL謂詞決定命中
560
- * 註: 支援欄位等值({欄位:值}, 值為null時比對IS NULL)與$eq、$ne、$gt、$gte、$lt、$lte、$in、$nin、$not、$regex($options僅i)、$exists, 以及$and、$or、$nor
561
- * 註: 不支援之運算子、非純量之值、與欄位型別不符之純量(如數值欄給'abc')一律reject並發出error事件, 不靜默忽略或改變語意
562
- * 註: 主鍵欄之條件值依主鍵欄型別正規化而與selectByPk等一致(如字串類主鍵欄之{id:123}即{id:'123'}, 整數類主鍵欄之'12'即12), 型別不符或無效者reject
563
- * 註: NULL依SQL三值邏輯, 故$ne、$nin、$not、$nor不含該欄為NULL之數據; $exists:false即IS NULL
564
- * 註: $regex僅支援字面子字串(含未跳脫正規式元字元者reject, 可用反斜線跳脫), 給i時不分大小寫, 未給i時大小寫依資料庫定序(sqlite之LIKE與mssql預設定序皆不分)
565
- * 註: 欄位值為陣列時視同$in, 與MongoDB之陣列比對不同
566
- * 註: find未給或為空物件時回傳全部數據; find非物件時亦回傳全部數據(現況保留)
556
+ * 使用須知(條件find為系列白名單, 規則同delAll, 見CLAUDE_rulebook.md之R11):
557
+ * 1. 不給條件即查詢全部數據: find未給、為undefined或為{}時回傳全部數據; 給了條件才是部分查詢。
558
+ * 2. 傳了值卻不是條件物件(null、陣列含[]與[{...}]、字串、數值、布林、函數、Date、RegExp、Map、Set、類別實例等)
559
+ * 一律整批reject, 不視為{}。
560
+ * 3. 條件僅支援系列白名單: 欄位等值{欄:純量}(多欄為AND)、欄位運算子$eq $ne $gt $gte $lt $lte(值為純量)與
561
+ * $in $nin(值為純量陣列)、文件層$and $or(值為條件物件之非空陣列, 最多999項)。純量為字串、有限數字、布林、有效Date;
562
+ * null僅可用於欄位等值、$eq、$ne。白名單外之運算子($not $nor $regex $options $exists $where $expr $like $ilike等)、
563
+ * sequelize之Op Symbol、RegExp值、陣列值(請改用$in)、欄位層$and/$or、函數值、Symbol鍵、undefined值、空的$nin/$and/$or等
564
+ * 一律整批reject, 訊息為invalid find: 原因 at [路徑], 且於載入model與連線前即檢核。
565
+ * 4. 欄名須完全等於model之屬性名或資料庫欄名(區分大小寫), 且為字母或底線開頭之字母/數字/底線(最多128字元);
566
+ * 純量須符合欄位型別(如數值欄給'abc'會reject); 主鍵欄之條件值依主鍵欄型別正規化(字串類主鍵欄之{id:123}即{id:'123'})。
567
+ * 5. 與delAll共用同一檢核與同一條件, select(find)命中之數據即delAll(find)刪除之數據。
568
+ * 6. 語意差異(SQL式): $ne/$nin不命中欄位為NULL之數據(三值邏輯)。需明確表達時可用可攜寫法:
569
+ * 排除NULL為{$and:[{f:{$ne:null}},{f:{$ne:x}}]}, 含NULL為{$or:[{f:null},{f:{$ne:x}}]}; 字串比對之大小寫依資料庫定序。
570
+ *
567
571
  * 註: 恆回傳陣列, 無符合數據回傳空陣列
568
572
  *
569
573
  * @memberOf WOrmReladb
570
- * @param {Object} [find={}] 輸入查詢條件物件
574
+ * @param {Object} [find={}] 輸入查詢條件物件(系列白名單, 規則同delAll之使用須知第1-4點); 未給、undefined或{}回傳全部數據; 非條件物件或白名單外運算子整批reject
571
575
  * @param {Object} [option={}] 輸入設定物件,預設為{}
572
576
  * @param {Object} [option.instance=null] 輸入實例instance物件,預設為null
573
577
  * @param {Object} [option.transaction=null] 輸入交易(transaction)物件,預設為null
@@ -595,13 +599,20 @@ function WOrmReladb(opt = {}) {
595
599
  //si
596
600
  let si = instance
597
601
 
602
+ //inited, 本次呼叫是否已進入initSequelize(僅此時finally才關閉sequelize; 預檢失敗於其前者不得關閉呼叫端先前持有之連線)
603
+ let inited = false
604
+
598
605
  try {
599
606
 
600
607
  //check, 實例已關閉屬整批性錯誤, 於入口快速失敗
601
608
  procClosed(instance)
602
609
 
610
+ //chkFindShape, 條件形狀不合法者(系列白名單, R11)於載入model與建立sequelize實例之前即拋錯: 不連線、不送出任何SQL, reject並發出error事件; 其後只使用檢核後之複本
611
+ let fd = chkFindShape(find)
612
+
603
613
  //initSequelize, 內部自動初始化須在try內: 其例外(如驅動缺失)與si.err同屬整批性錯誤, 方能於reject前發出error事件, 已建構之sequelize亦由finally關閉
604
614
  if (instance === null) {
615
+ inited = true
605
616
  si = await initSequelize()
606
617
  }
607
618
 
@@ -613,8 +624,8 @@ function WOrmReladb(opt = {}) {
613
624
  //md
614
625
  let md = si.mds[opt.cl]
615
626
 
616
- //useFind, 與delAll共用cvFind, 條件不合法者於此拋錯而reject並發出error事件
617
- let useFind = cvFind(find, getFindCtx(md))
627
+ //useFind, 與delAll共用cvFind(對複本再檢核一次, 冪等), 欄名、欄位型別等翻譯層不合法者於此拋錯而reject並發出error事件
628
+ let useFind = cvFind(fd, getFindCtx(md))
618
629
 
619
630
  //setting, raw令回傳純數據物件而不含資料庫內部欄位
620
631
  let setting = {
@@ -639,7 +650,7 @@ function WOrmReladb(opt = {}) {
639
650
  finally {
640
651
 
641
652
  //closeSequelize
642
- if (instance === null) { //內部自動初始化得close
653
+ if (instance === null && inited) { //內部自動初始化得close
643
654
  await closeSequelize('select')
644
655
  }
645
656
 
@@ -1600,16 +1611,29 @@ function WOrmReladb(opt = {}) {
1600
1611
 
1601
1612
 
1602
1613
  /**
1603
- * 依條件刪除多筆數據,需與del分開,避免未傳數據導致直接刪除全表
1614
+ * 依條件刪除多筆數據(破壞性操作, 須審慎使用, 非必要不用; 刪除單筆請用del), 需與del分開,避免未傳數據導致直接刪除全表
1615
+ *
1616
+ * 使用須知:
1617
+ * 1. 不給條件即刪除全部數據: find未給、為undefined或為{}時, 刪除資料表內全部數據, 不另行確認。給了條件才是部分刪除。
1618
+ * 2. 傳了值卻不是條件物件(null、陣列含[]與[{...}]、字串、數值、布林、函數、Date、RegExp、Map、Set、類別實例等)
1619
+ * 一律整批reject, 不視為{}, 不刪除任何數據。
1620
+ * 3. 條件僅支援系列白名單: 欄位等值{欄:純量}(多欄為AND)、欄位運算子$eq $ne $gt $gte $lt $lte(值為純量)與
1621
+ * $in $nin(值為純量陣列)、文件層$and $or(值為條件物件之非空陣列, 最多999項)。純量為字串、有限數字、布林、有效Date;
1622
+ * null僅可用於欄位等值、$eq、$ne。白名單外之運算子($not $nor $regex $options $exists $where $expr $like $ilike等)、
1623
+ * sequelize之Op Symbol、RegExp值、陣列值(請改用$in)、欄位層$and/$or、子查詢、函數值、Symbol鍵、undefined值、
1624
+ * 空的$nin/$and/$or等一律整批reject, 訊息為invalid find: 原因 at [路徑], 且不刪除任何數據。
1625
+ * 4. 與select共用同一檢核與同一條件, select(find)命中之數據即本函數刪除之數據; 建議先以select(find)確認命中範圍再刪除。
1626
+ * 欄名須完全等於model之屬性名或資料庫欄名(區分大小寫); 純量須符合欄位型別; 主鍵欄之條件值依主鍵欄型別正規化。
1627
+ * 5. 條件值若來自可能為undefined、null或空陣列之變數, 呼叫端須先自行判斷; undefined值會reject而非被忽略,
1628
+ * 空的$nin會reject, $in:[]則為恆假(刪除0筆)。
1629
+ * 6. 語意差異(SQL式): $ne/$nin不命中欄位為NULL之數據(三值邏輯)。需明確表達時可用可攜寫法:
1630
+ * 排除NULL為{$and:[{f:{$ne:null}},{f:{$ne:x}}]}, 含NULL為{$or:[{f:null},{f:{$ne:x}}]}; 字串比對之大小寫依資料庫定序。
1604
1631
  *
1605
1632
  * 註: n與nDeleted皆為實際刪除筆數,兩者恆相等,n不得取全表筆數
1606
- * 註: find未給或為空物件時刪除全部數據;條件無命中時回{n:0,nDeleted:0,ok:1},不視為錯誤
1607
- * 註: find由cvFind轉譯且與select共用,刪除之數據即select(find)命中之數據;支援之條件與限制同select
1608
- * 註: 不支援之運算子、非純量之值、與欄位型別不符之純量一律reject並發出error事件,不刪除任何數據;主鍵欄之條件值依主鍵欄型別正規化,同select
1609
- * 註: find非物件(null、陣列、字串、數字)時刪除全部數據,此為現況保留,系列規格另案處理
1633
+ * 註: 條件無命中時回{n:0,nDeleted:0,ok:1},不視為錯誤
1610
1634
  *
1611
1635
  * @memberOf WOrmReladb
1612
- * @param {Object} [find={}] 輸入刪除條件物件,不給予find則代表刪除全部數據
1636
+ * @param {Object} [find={}] 輸入刪除條件物件(系列白名單, 見使用須知),不給予find則代表刪除全部數據
1613
1637
  * @param {Object} [option={}] 輸入設定物件,預設為{}
1614
1638
  * @param {Object} [option.instance=null] 輸入實例instance物件,預設為null
1615
1639
  * @param {Object} [option.transaction=null] 輸入交易(transaction)物件,預設為null
@@ -1637,13 +1661,20 @@ function WOrmReladb(opt = {}) {
1637
1661
  //si
1638
1662
  let si = instance
1639
1663
 
1664
+ //inited, 本次呼叫是否已進入initSequelize(僅此時finally才關閉sequelize; 預檢失敗於其前者不得關閉呼叫端先前持有之連線)
1665
+ let inited = false
1666
+
1640
1667
  try {
1641
1668
 
1642
1669
  //check, 實例已關閉屬整批性錯誤, 於入口快速失敗
1643
1670
  procClosed(instance)
1644
1671
 
1672
+ //chkFindShape, 條件形狀不合法者(系列白名單, R11)於載入model與建立sequelize實例之前即拋錯: 不連線、不送出任何SQL、不刪除任何數據; 其後只使用檢核後之複本
1673
+ let fd = chkFindShape(find)
1674
+
1645
1675
  //initSequelize, 內部自動初始化須在try內: 其例外(如驅動缺失)與si.err同屬整批性錯誤, 方能於reject前發出error事件, 已建構之sequelize亦由finally關閉
1646
1676
  if (instance === null) {
1677
+ inited = true
1647
1678
  si = await initSequelize()
1648
1679
  }
1649
1680
 
@@ -1655,8 +1686,8 @@ function WOrmReladb(opt = {}) {
1655
1686
  //md
1656
1687
  let md = si.mds[opt.cl]
1657
1688
 
1658
- //useFind, 與select共用cvFind, 令刪除之數據即select命中之數據; 條件不合法者於此拋錯而不刪除任何數據
1659
- let useFind = cvFind(find, getFindCtx(md))
1689
+ //useFind, 與select共用cvFind(對複本再檢核一次, 冪等), 令刪除之數據即select命中之數據; 翻譯層不合法者於此拋錯而不刪除任何數據
1690
+ let useFind = cvFind(fd, getFindCtx(md))
1660
1691
 
1661
1692
  //chkScopeForDelAll, model之預設scope會使刪除對象與select分歧者拒絕
1662
1693
  chkScopeForDelAll(md)
@@ -1688,7 +1719,7 @@ function WOrmReladb(opt = {}) {
1688
1719
  finally {
1689
1720
 
1690
1721
  //closeSequelize
1691
- if (instance === null) { //內部自動初始化得close
1722
+ if (instance === null && inited) { //內部自動初始化得close
1692
1723
  await closeSequelize('delAll')
1693
1724
  }
1694
1725