oak-domain 3.0.3 → 4.0.0
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/lib/actions/action.d.ts +16 -16
- package/lib/actions/action.js +17 -17
- package/lib/actions/relation.d.ts +5 -5
- package/lib/actions/relation.js +25 -38
- package/lib/base-app-domain/ActionAuth/Schema.d.ts +186 -160
- package/lib/base-app-domain/ActionAuth/Storage.js +39 -42
- package/lib/base-app-domain/ActionDefDict.d.ts +8 -9
- package/lib/base-app-domain/ActionDefDict.js +9 -11
- package/lib/base-app-domain/EntityDict.d.ts +28 -24
- package/lib/base-app-domain/I18n/Schema.d.ts +129 -129
- package/lib/base-app-domain/I18n/Schema.js +2 -2
- package/lib/base-app-domain/I18n/Storage.d.ts +3 -3
- package/lib/base-app-domain/I18n/Storage.js +59 -59
- package/lib/base-app-domain/Modi/Action.d.ts +10 -10
- package/lib/base-app-domain/Modi/Action.js +14 -14
- package/lib/base-app-domain/Modi/Schema.d.ts +136 -136
- package/lib/base-app-domain/Modi/Storage.js +63 -63
- package/lib/base-app-domain/ModiEntity/Schema.d.ts +384 -311
- package/lib/base-app-domain/ModiEntity/Storage.js +30 -30
- package/lib/base-app-domain/Oper/Schema.d.ts +153 -152
- package/lib/base-app-domain/Oper/Storage.js +38 -38
- package/lib/base-app-domain/OperEntity/Schema.d.ts +373 -300
- package/lib/base-app-domain/OperEntity/Storage.js +30 -30
- package/lib/base-app-domain/Path/Schema.d.ts +149 -0
- package/lib/base-app-domain/Path/Schema.js +2 -0
- package/lib/base-app-domain/Path/Storage.d.ts +3 -0
- package/lib/base-app-domain/Path/Storage.js +54 -0
- package/lib/base-app-domain/Relation/Schema.d.ts +188 -188
- package/lib/base-app-domain/Relation/Storage.js +54 -54
- package/lib/base-app-domain/Relation.d.ts +2 -10
- package/lib/base-app-domain/Relation.js +4 -10
- package/lib/base-app-domain/RelationAuth/Schema.d.ts +214 -180
- package/lib/base-app-domain/RelationAuth/Storage.js +44 -46
- package/lib/base-app-domain/Storage.js +31 -27
- package/lib/base-app-domain/User/Action.d.ts +10 -10
- package/lib/base-app-domain/User/Action.js +12 -12
- package/lib/base-app-domain/User/Schema.d.ts +210 -197
- package/lib/base-app-domain/User/Storage.js +33 -33
- package/lib/base-app-domain/UserEntityClaim/Schema.d.ts +264 -0
- package/lib/base-app-domain/UserEntityClaim/Schema.js +2 -0
- package/lib/base-app-domain/UserEntityClaim/Storage.d.ts +3 -0
- package/lib/base-app-domain/UserEntityClaim/Storage.js +37 -0
- package/lib/base-app-domain/UserEntityGrant/Action.d.ts +5 -5
- package/lib/base-app-domain/UserEntityGrant/Action.js +5 -5
- package/lib/base-app-domain/UserEntityGrant/Schema.d.ts +131 -157
- package/lib/base-app-domain/UserEntityGrant/Storage.js +25 -29
- package/lib/base-app-domain/UserRelation/Schema.d.ts +208 -194
- package/lib/base-app-domain/UserRelation/Storage.js +56 -56
- package/lib/base-app-domain/_SubQuery.d.ts +142 -112
- package/lib/base-app-domain/index.d.ts +4 -4
- package/lib/base-app-domain/index.js +7 -7
- package/lib/checkers/index.d.ts +5 -5
- package/lib/checkers/index.js +13 -14
- package/lib/compiler/entities.d.ts +2 -0
- package/lib/compiler/entities.js +7 -0
- package/lib/compiler/env.d.ts +13 -14
- package/lib/compiler/env.js +45 -50
- package/lib/compiler/localeBuilder.d.ts +27 -22
- package/lib/compiler/localeBuilder.js +184 -169
- package/lib/compiler/schemalBuilder.d.ts +27 -11
- package/lib/compiler/schemalBuilder.js +3569 -3787
- package/lib/entities/ActionAuth.d.ts +10 -12
- package/lib/entities/ActionAuth.js +31 -29
- package/lib/entities/I18n.d.ts +9 -9
- package/lib/entities/I18n.js +36 -37
- package/lib/entities/Modi.js +49 -49
- package/lib/entities/ModiEntity.js +18 -18
- package/lib/entities/Oper.js +21 -21
- package/lib/entities/OperEntity.js +18 -18
- package/lib/entities/Path.d.ts +8 -0
- package/lib/entities/Path.js +35 -0
- package/lib/entities/Relation.d.ts +8 -8
- package/lib/entities/Relation.js +35 -35
- package/lib/entities/RelationAuth.d.ts +8 -8
- package/lib/entities/RelationAuth.js +34 -34
- package/lib/entities/User.js +31 -31
- package/lib/entities/UserEntityClaim.d.ts +13 -0
- package/lib/entities/UserEntityClaim.js +17 -0
- package/lib/entities/UserEntityGrant.d.ts +9 -8
- package/lib/entities/UserEntityGrant.js +15 -18
- package/lib/entities/UserRelation.d.ts +10 -10
- package/lib/entities/UserRelation.js +38 -38
- package/lib/index.d.ts +23 -0
- package/lib/index.js +37 -0
- package/lib/store/AsyncRowStore.d.ts +60 -58
- package/lib/store/AsyncRowStore.js +118 -190
- package/lib/store/CascadeStore.d.ts +104 -103
- package/lib/store/CascadeStore.js +1688 -2036
- package/lib/store/RelationAuth.d.ts +96 -103
- package/lib/store/RelationAuth.js +1336 -1492
- package/lib/store/SyncRowStore.d.ts +29 -29
- package/lib/store/SyncRowStore.js +50 -49
- package/lib/store/TriggerExecutor.d.ts +38 -31
- package/lib/store/TriggerExecutor.js +459 -532
- package/lib/store/actionAuth.d.ts +4 -4
- package/lib/store/actionAuth.js +25 -40
- package/lib/store/actionDef.d.ts +10 -10
- package/lib/store/actionDef.js +278 -353
- package/lib/store/checker.d.ts +26 -26
- package/lib/store/checker.js +487 -623
- package/lib/store/filter.d.ts +85 -123
- package/lib/store/filter.js +1651 -1761
- package/lib/store/modi.d.ts +13 -13
- package/lib/store/modi.js +254 -315
- package/lib/store/relation.d.ts +12 -12
- package/lib/store/relation.js +67 -67
- package/lib/timers/oper.d.ts +18 -18
- package/lib/timers/oper.js +57 -60
- package/lib/timers/vaccum.d.ts +20 -20
- package/lib/timers/vaccum.js +111 -176
- package/lib/triggers/index.d.ts +5 -5
- package/lib/triggers/index.js +8 -8
- package/lib/types/Action.d.ts +20 -20
- package/lib/types/AppLoader.d.ts +17 -11
- package/lib/types/AppLoader.js +10 -10
- package/lib/types/Aspect.d.ts +1 -3
- package/lib/types/Auth.d.ts +70 -74
- package/lib/types/Cluster.d.ts +5 -0
- package/lib/types/Cluster.js +2 -0
- package/lib/types/Connector.d.ts +38 -34
- package/lib/types/Connector.js +2 -9
- package/lib/types/DataType.d.ts +25 -24
- package/lib/types/DataType.js +6 -6
- package/lib/types/Demand.d.ts +88 -88
- package/lib/types/Demand.js +10 -10
- package/lib/types/Endpoint.d.ts +11 -11
- package/lib/types/Entity.d.ts +203 -198
- package/lib/types/Entity.js +15 -15
- package/lib/types/EntityDesc.d.ts +9 -8
- package/lib/types/EntityDesc.js +2 -2
- package/lib/types/Environment.d.ts +88 -57
- package/lib/types/Environment.js +2 -2
- package/lib/types/Exception.d.ts +147 -120
- package/lib/types/Exception.js +406 -406
- package/lib/types/Expression.d.ts +163 -163
- package/lib/types/Expression.js +397 -427
- package/lib/types/Geo.d.ts +18 -18
- package/lib/types/Locale.d.ts +25 -25
- package/lib/types/Logger.d.ts +6 -6
- package/lib/types/Polyfill.d.ts +24 -24
- package/lib/types/Port.d.ts +18 -18
- package/lib/types/RowStore.d.ts +18 -18
- package/lib/types/RowStore.js +33 -34
- package/lib/types/Storage.d.ts +58 -57
- package/lib/types/Style.d.ts +11 -11
- package/lib/types/Timer.d.ts +14 -14
- package/lib/types/Trigger.d.ts +124 -108
- package/lib/types/Trigger.js +58 -54
- package/lib/types/Watcher.d.ts +19 -19
- package/lib/types/index.d.ts +26 -24
- package/lib/types/index.js +29 -27
- package/lib/types/schema/DataTypes.d.ts +34 -34
- package/lib/utils/SimpleConnector.d.ts +64 -50
- package/lib/utils/SimpleConnector.js +206 -184
- package/lib/utils/assert.d.ts +5 -5
- package/lib/utils/assert.js +9 -9
- package/lib/utils/concurrent.d.ts +15 -15
- package/lib/utils/concurrent.js +63 -89
- package/lib/utils/date.js +18 -18
- package/lib/utils/{url.d.ts → domain.d.ts} +1 -1
- package/lib/utils/{url.js → domain.js} +11 -12
- package/lib/utils/geo.js +24 -24
- package/lib/utils/lodash.d.ts +24 -20
- package/lib/utils/lodash.js +46 -55
- package/lib/utils/mask.js +34 -35
- package/lib/utils/money.d.ts +6 -6
- package/lib/utils/money.js +51 -40
- package/lib/utils/projection.d.ts +4 -0
- package/lib/utils/projection.js +15 -0
- package/lib/utils/random/random.js +19 -24
- package/lib/utils/random/random.mp.js +14 -25
- package/lib/utils/random/random.native.d.ts +1 -0
- package/lib/utils/random/random.native.js +14 -0
- package/lib/utils/random/random.web.js +11 -17
- package/lib/utils/string.d.ts +28 -28
- package/lib/utils/string.js +69 -82
- package/lib/utils/url/index.d.ts +7 -0
- package/lib/utils/url/index.js +8 -0
- package/lib/utils/url/index.mp.d.ts +4 -0
- package/lib/utils/url/index.mp.js +8 -0
- package/lib/utils/url/index.native.d.ts +12 -0
- package/lib/utils/url/index.native.js +7 -0
- package/lib/utils/url/index.web.d.ts +12 -0
- package/lib/utils/url/index.web.js +7 -0
- package/lib/utils/uuid.d.ts +17 -17
- package/lib/utils/uuid.js +218 -257
- package/lib/utils/validator.d.ts +26 -25
- package/lib/utils/validator.js +131 -128
- package/lib/utils/version.js +21 -21
- package/package.json +51 -49
- package/src/entities/ActionAuth.ts +41 -41
- package/src/entities/I18n.ts +45 -46
- package/src/entities/Modi.ts +69 -69
- package/src/entities/ModiEntity.ts +26 -26
- package/src/entities/Oper.ts +32 -32
- package/src/entities/OperEntity.ts +27 -27
- package/src/entities/Path.ts +43 -0
- package/src/entities/Relation.ts +43 -43
- package/src/entities/RelationAuth.ts +44 -43
- package/src/entities/User.ts +48 -48
- package/src/entities/UserEntityClaim.ts +30 -0
- package/src/entities/UserEntityGrant.ts +24 -27
- package/src/entities/UserRelation.ts +50 -50
package/lib/store/filter.js
CHANGED
|
@@ -1,1761 +1,1651 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
{
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
for (
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
if (
|
|
349
|
-
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
attr2 === '$
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
if (r) {
|
|
695
|
-
return true;
|
|
696
|
-
}
|
|
697
|
-
return false;
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
if (
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
//
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
}
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
*
|
|
1410
|
-
*
|
|
1411
|
-
*
|
|
1412
|
-
* @param
|
|
1413
|
-
* @param
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
*
|
|
1427
|
-
*
|
|
1428
|
-
*
|
|
1429
|
-
*
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
if (
|
|
1457
|
-
return
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
if (
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
}
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
}
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
*
|
|
1562
|
-
* @param
|
|
1563
|
-
* @param
|
|
1564
|
-
* @param
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
var ele2_2 = ele;
|
|
1653
|
-
return context.count(ele2_2.entity, {
|
|
1654
|
-
filter: ele2_2.filter
|
|
1655
|
-
}, {});
|
|
1656
|
-
}
|
|
1657
|
-
var ele2 = ele;
|
|
1658
|
-
return checkDeduceFilters(ele2, context);
|
|
1659
|
-
});
|
|
1660
|
-
// or只要有一个条件通过就返回true
|
|
1661
|
-
if (orResult.find(function (ele) { return ele instanceof Promise; })) {
|
|
1662
|
-
return Promise.all(orResult).then(function (or) {
|
|
1663
|
-
var e_16, _a;
|
|
1664
|
-
try {
|
|
1665
|
-
for (var or_1 = tslib_1.__values(or), or_1_1 = or_1.next(); !or_1_1.done; or_1_1 = or_1.next()) {
|
|
1666
|
-
var ele = or_1_1.value;
|
|
1667
|
-
if (ele === true || ele === 0) {
|
|
1668
|
-
return true;
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
catch (e_16_1) { e_16 = { error: e_16_1 }; }
|
|
1673
|
-
finally {
|
|
1674
|
-
try {
|
|
1675
|
-
if (or_1_1 && !or_1_1.done && (_a = or_1.return)) _a.call(or_1);
|
|
1676
|
-
}
|
|
1677
|
-
finally { if (e_16) throw e_16.error; }
|
|
1678
|
-
}
|
|
1679
|
-
return false;
|
|
1680
|
-
});
|
|
1681
|
-
}
|
|
1682
|
-
try {
|
|
1683
|
-
for (var orResult_1 = tslib_1.__values(orResult), orResult_1_1 = orResult_1.next(); !orResult_1_1.done; orResult_1_1 = orResult_1.next()) {
|
|
1684
|
-
var ele = orResult_1_1.value;
|
|
1685
|
-
if (ele === true || ele === 0) {
|
|
1686
|
-
return true;
|
|
1687
|
-
}
|
|
1688
|
-
}
|
|
1689
|
-
}
|
|
1690
|
-
catch (e_14_1) { e_14 = { error: e_14_1 }; }
|
|
1691
|
-
finally {
|
|
1692
|
-
try {
|
|
1693
|
-
if (orResult_1_1 && !orResult_1_1.done && (_b = orResult_1.return)) _b.call(orResult_1);
|
|
1694
|
-
}
|
|
1695
|
-
finally { if (e_14) throw e_14.error; }
|
|
1696
|
-
}
|
|
1697
|
-
return false;
|
|
1698
|
-
}
|
|
1699
|
-
exports.checkDeduceFilters = checkDeduceFilters;
|
|
1700
|
-
/**
|
|
1701
|
-
* 检查filter是否包含contained(filter查询的数据是contained查询数据的子集)
|
|
1702
|
-
* @param entity
|
|
1703
|
-
* @param context
|
|
1704
|
-
* @param contained
|
|
1705
|
-
* @param filter
|
|
1706
|
-
* @param dataCompare
|
|
1707
|
-
* @returns
|
|
1708
|
-
*/
|
|
1709
|
-
function checkFilterContains(entity, context, contained, filter, dataCompare) {
|
|
1710
|
-
if (!filter) {
|
|
1711
|
-
throw new types_1.OakRowInconsistencyException();
|
|
1712
|
-
}
|
|
1713
|
-
var schema = context.getSchema();
|
|
1714
|
-
var result = contains(entity, schema, filter, contained);
|
|
1715
|
-
if (typeof result === 'boolean') {
|
|
1716
|
-
return result;
|
|
1717
|
-
}
|
|
1718
|
-
if (dataCompare) {
|
|
1719
|
-
return checkDeduceFilters(result, context);
|
|
1720
|
-
}
|
|
1721
|
-
return false;
|
|
1722
|
-
}
|
|
1723
|
-
exports.checkFilterContains = checkFilterContains;
|
|
1724
|
-
function checkFilterRepel(entity, context, filter1, filter2, dataCompare) {
|
|
1725
|
-
if (!filter2) {
|
|
1726
|
-
throw new types_1.OakRowInconsistencyException();
|
|
1727
|
-
}
|
|
1728
|
-
var schema = context.getSchema();
|
|
1729
|
-
var result = repel(entity, schema, filter2, filter1);
|
|
1730
|
-
if (typeof result === 'boolean') {
|
|
1731
|
-
return result;
|
|
1732
|
-
}
|
|
1733
|
-
if (dataCompare) {
|
|
1734
|
-
return checkDeduceFilters(result, context);
|
|
1735
|
-
}
|
|
1736
|
-
return false;
|
|
1737
|
-
}
|
|
1738
|
-
exports.checkFilterRepel = checkFilterRepel;
|
|
1739
|
-
/* export function getCascadeEntityFilter<ED extends EntityDict & BaseEntityDict, T extends keyof ED>(
|
|
1740
|
-
filter: NonNullable<ED[T]['Selection']['filter']>,
|
|
1741
|
-
attr: keyof NonNullable<ED[T]['Selection']['filter']>
|
|
1742
|
-
): ED[keyof ED]['Selection']['filter'] {
|
|
1743
|
-
const filters: ED[keyof ED]['Selection']['filter'][] = [];
|
|
1744
|
-
if (filter![attr]) {
|
|
1745
|
-
assert(typeof filter![attr] === 'object');
|
|
1746
|
-
filters.push(filter![attr]);
|
|
1747
|
-
}
|
|
1748
|
-
if (filter.$and) {
|
|
1749
|
-
filter.$and.forEach(
|
|
1750
|
-
(ele: NonNullable<ED[T]['Selection']['filter']>) => {
|
|
1751
|
-
const f2 = getCascadeEntityFilter(ele, attr);
|
|
1752
|
-
if (f2) {
|
|
1753
|
-
filters.push(f2)
|
|
1754
|
-
}
|
|
1755
|
-
}
|
|
1756
|
-
);
|
|
1757
|
-
}
|
|
1758
|
-
if (filters.length > 0) {
|
|
1759
|
-
return combineFilters(filters);
|
|
1760
|
-
}
|
|
1761
|
-
} */
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.translateFilterToObjectPredicate = exports.checkFilterRepel = exports.checkFilterContains = exports.makeTreeDescendantFilter = exports.makeTreeAncestorFilter = exports.same = exports.getRelevantIds = exports.judgeValueRelation = exports.combineFilters = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const assert_1 = tslib_1.__importDefault(require("assert"));
|
|
6
|
+
const types_1 = require("../types");
|
|
7
|
+
const lodash_1 = require("../utils/lodash");
|
|
8
|
+
const relation_1 = require("./relation");
|
|
9
|
+
/* function getFilterAttributes(filter: Record<string, any>) {
|
|
10
|
+
const attributes = [] as string[];
|
|
11
|
+
|
|
12
|
+
for (const attr in filter) {
|
|
13
|
+
if (attr.startsWith('$') || attr.startsWith('#')) {
|
|
14
|
+
if (['$and', '$or'].includes(attr)) {
|
|
15
|
+
for (const f of filter[attr]) {
|
|
16
|
+
const a = getFilterAttributes(f);
|
|
17
|
+
attributes.push(...a);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else if (attr === '$not') {
|
|
21
|
+
const a = getFilterAttributes(filter[attr]);
|
|
22
|
+
attributes.push(...a);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
attributes.push(attr);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return uniq(attributes);
|
|
31
|
+
} */
|
|
32
|
+
/**
|
|
33
|
+
* 尽量合并外键的连接,防止在数据库中join的对象过多
|
|
34
|
+
* @param entity
|
|
35
|
+
* @param schema
|
|
36
|
+
* @param filters
|
|
37
|
+
* @returns
|
|
38
|
+
*/
|
|
39
|
+
function addFilterSegment(entity, schema, ...filters) {
|
|
40
|
+
let filter;
|
|
41
|
+
const addIntoAnd = (f) => {
|
|
42
|
+
(0, assert_1.default)(filter);
|
|
43
|
+
if (filter.$and) {
|
|
44
|
+
filter.$and.push(f);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
filter.$and = [f];
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const addSingleAttr = (attr, value) => {
|
|
51
|
+
(0, assert_1.default)(filter);
|
|
52
|
+
if (!filter[attr]) {
|
|
53
|
+
filter[attr] = value;
|
|
54
|
+
}
|
|
55
|
+
// 只优化一种情况,就是两个都等值且相等
|
|
56
|
+
else if (filter[attr] === value) {
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
addIntoAnd({
|
|
60
|
+
[attr]: value,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const manyToOneFilters = {};
|
|
65
|
+
const addManyToOneFilter = (attr, entity2, filter) => {
|
|
66
|
+
if (manyToOneFilters[attr]) {
|
|
67
|
+
manyToOneFilters[attr].push([entity2, filter]);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
manyToOneFilters[attr] = [[entity2, filter]];
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const oneToManyFilters = {};
|
|
74
|
+
const addOneToManyFilter = (attr, entity2, filter) => {
|
|
75
|
+
if (oneToManyFilters[attr]) {
|
|
76
|
+
oneToManyFilters[attr].push([entity2, filter]);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
oneToManyFilters[attr] = [[entity2, filter]];
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const addInner = (f) => {
|
|
83
|
+
if (f) {
|
|
84
|
+
if (!filter) {
|
|
85
|
+
filter = {};
|
|
86
|
+
}
|
|
87
|
+
if (f.hasOwnProperty('$or')) {
|
|
88
|
+
// 如果有or是无法优化的,直接作为一个整体加入$and
|
|
89
|
+
addIntoAnd(f);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
for (const attr in f) {
|
|
93
|
+
if (attr === '$and') {
|
|
94
|
+
f[attr].forEach((f2) => addInner(f2));
|
|
95
|
+
}
|
|
96
|
+
else if (attr.startsWith('$')) {
|
|
97
|
+
addIntoAnd({
|
|
98
|
+
[attr]: f[attr],
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
else if (attr.startsWith('#')) {
|
|
102
|
+
(0, assert_1.default)(!filter[attr] || filter[attr] === f[attr]);
|
|
103
|
+
filter[attr] = f[attr];
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
const rel = (0, relation_1.judgeRelation)(schema, entity, attr);
|
|
107
|
+
if (rel === 1) {
|
|
108
|
+
addSingleAttr(attr, f[attr]);
|
|
109
|
+
}
|
|
110
|
+
else if (rel === 2) {
|
|
111
|
+
addManyToOneFilter(attr, attr, f[attr]);
|
|
112
|
+
}
|
|
113
|
+
else if (typeof rel === 'string') {
|
|
114
|
+
addManyToOneFilter(attr, rel, f[attr]);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
(0, assert_1.default)(rel instanceof Array);
|
|
118
|
+
addOneToManyFilter(attr, rel[0], f[attr]);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
filters.forEach(ele => addInner(ele));
|
|
125
|
+
for (const attr in manyToOneFilters) {
|
|
126
|
+
const filters2 = manyToOneFilters[attr].map(ele => ele[1]);
|
|
127
|
+
const combined = addFilterSegment(manyToOneFilters[attr][0][0], schema, ...filters2);
|
|
128
|
+
addSingleAttr(attr, combined);
|
|
129
|
+
}
|
|
130
|
+
for (const attr in oneToManyFilters) {
|
|
131
|
+
const filters2 = oneToManyFilters[attr].map(ele => ele[1]);
|
|
132
|
+
const sqpOps = filters2.map(ele => ele['#sqp'] || 'in');
|
|
133
|
+
// 只有全部是同一个子查询算子才能实施合并
|
|
134
|
+
if ((0, lodash_1.uniq)(sqpOps).length > 1) {
|
|
135
|
+
filters2.forEach(ele => {
|
|
136
|
+
addIntoAnd({
|
|
137
|
+
[attr]: ele,
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const sqpOp = sqpOps[0];
|
|
143
|
+
if (sqpOp === 'not in') {
|
|
144
|
+
// not in 在此变成or查询
|
|
145
|
+
const unioned = unionFilterSegment(oneToManyFilters[attr][0][0], schema, ...filters2);
|
|
146
|
+
addSingleAttr(attr, Object.assign(unioned, {
|
|
147
|
+
['#sqp']: sqpOp,
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
(0, assert_1.default)(sqpOp === 'in'); // all 和 not all暂时不会出现
|
|
152
|
+
const combined = addFilterSegment(oneToManyFilters[attr][0][0], schema, ...filters2);
|
|
153
|
+
addSingleAttr(attr, Object.assign(combined, {
|
|
154
|
+
['#sqp']: sqpOp,
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return filter;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* 尽量合并外键的连接,防止在数据库中join的对象过多
|
|
163
|
+
* @param entity
|
|
164
|
+
* @param schema
|
|
165
|
+
* @param filters
|
|
166
|
+
* @returns
|
|
167
|
+
*/
|
|
168
|
+
function unionFilterSegment(entity, schema, ...filters) {
|
|
169
|
+
let filter;
|
|
170
|
+
const possibleCombiningAttrs = (f1, f2) => {
|
|
171
|
+
let pca1s = [], pca2s = [];
|
|
172
|
+
const attributes1 = Object.keys(f1);
|
|
173
|
+
const attributes2 = Object.keys(f2);
|
|
174
|
+
for (const a of attributes1) {
|
|
175
|
+
if (a.startsWith('#')) {
|
|
176
|
+
if (f1[a] !== f2[a]) {
|
|
177
|
+
// metadata不相等,无法合并
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
pca1s.push(a);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
for (const a of attributes2) {
|
|
186
|
+
if (a.startsWith('#')) {
|
|
187
|
+
if (f1[a] !== f2[a]) {
|
|
188
|
+
// metadata不相等,无法合并
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
pca2s.push(a);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (pca1s.length > 1 || pca2s.length > 1) {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
(0, assert_1.default)(pca1s.length === 1 && pca2s.length === 1);
|
|
200
|
+
if (pca1s[0] !== pca2s[0] && pca1s[0] !== '$or' && pca2s[0] !== '$or') {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
return [pca1s[0], pca2s[0]];
|
|
204
|
+
};
|
|
205
|
+
/**
|
|
206
|
+
* 尝试合并同一个属性到f1上,这里只合并等值查询和$in
|
|
207
|
+
* @param f1
|
|
208
|
+
* @param f2
|
|
209
|
+
* @param attr
|
|
210
|
+
* @param justTry
|
|
211
|
+
*/
|
|
212
|
+
const tryMergeAttributeValue = (f1, f2, attr, justTry) => {
|
|
213
|
+
const op1 = typeof f1[attr] === 'object' && Object.keys(f1[attr])[0];
|
|
214
|
+
const op2 = typeof f2[attr] === 'object' && Object.keys(f2[attr])[0];
|
|
215
|
+
if (!op1 && op2 && ['$eq', '$in'].includes(op2)) {
|
|
216
|
+
if (justTry) {
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
Object.assign(f1, {
|
|
220
|
+
[attr]: {
|
|
221
|
+
$in: f2[attr][op2] instanceof Array ? f2[attr][op2].concat(f1[attr]) : [f1[attr], f2[attr][op2]],
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
else if (!op2 && op1 && ['$eq', '$in'].includes(op1)) {
|
|
227
|
+
if (justTry) {
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
Object.assign(f1, {
|
|
231
|
+
[attr]: {
|
|
232
|
+
$in: f1[attr][op1] instanceof Array ? f1[attr][op1].concat(f2[attr]) : [f1[op1][attr], f2[attr]],
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
else if (op1 && ['$eq', '$in'].includes(op1) && op2 && ['$eq', '$in'].includes(op2)) {
|
|
238
|
+
if (justTry) {
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
Object.assign(f1, {
|
|
242
|
+
[attr]: {
|
|
243
|
+
$in: f1[attr][op1] instanceof Array ? f1[attr][op1].concat(f2[attr][op2]) : [f1[attr][op1]].concat(f2[attr][op2]),
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
else if (!op1 && !op2) {
|
|
249
|
+
if (justTry) {
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
Object.assign(f1, {
|
|
253
|
+
[attr]: {
|
|
254
|
+
$in: [f1[attr], f2[attr]],
|
|
255
|
+
},
|
|
256
|
+
});
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
return false;
|
|
260
|
+
};
|
|
261
|
+
/**
|
|
262
|
+
* 把f2尝试combine到f1中,保持or的语义
|
|
263
|
+
* @param f1
|
|
264
|
+
* @param f2
|
|
265
|
+
* @returns
|
|
266
|
+
*/
|
|
267
|
+
const tryMergeFilters = (f1, f2, justTry) => {
|
|
268
|
+
const pcaResult = possibleCombiningAttrs(f1, f2);
|
|
269
|
+
if (!pcaResult) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
const [pca1, pca2] = pcaResult;
|
|
273
|
+
if (pca1 === '$or' && pca2 === '$or') {
|
|
274
|
+
// 如果双方都是or,有可能可以交叉合并,如:
|
|
275
|
+
/**
|
|
276
|
+
* {
|
|
277
|
+
$or: [
|
|
278
|
+
{
|
|
279
|
+
password: '1234',
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
ref: {
|
|
283
|
+
nickname: 'xc',
|
|
284
|
+
},
|
|
285
|
+
}
|
|
286
|
+
]
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
$or: [
|
|
290
|
+
{
|
|
291
|
+
ref: {
|
|
292
|
+
name: 'xc2',
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
password: 'dddd',
|
|
297
|
+
}
|
|
298
|
+
]
|
|
299
|
+
}
|
|
300
|
+
*/
|
|
301
|
+
for (const f21 of f2[pca2]) {
|
|
302
|
+
let success = false;
|
|
303
|
+
for (const f11 of f1[pca2]) {
|
|
304
|
+
if (tryMergeFilters(f11, f21, true)) {
|
|
305
|
+
success = true;
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
if (!success) {
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (justTry) {
|
|
314
|
+
return true;
|
|
315
|
+
}
|
|
316
|
+
for (const f21 of f2[pca2]) {
|
|
317
|
+
for (const f11 of f1[pca2]) {
|
|
318
|
+
if (tryMergeFilters(f11, f21)) {
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
else if (pca1 === '$or') {
|
|
326
|
+
for (const f11 of f1[pca1]) {
|
|
327
|
+
if (tryMergeFilters(f11, f2, justTry)) {
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
else if (pca2 === '$or') {
|
|
334
|
+
for (const f21 of f2[pca2]) {
|
|
335
|
+
if (!tryMergeFilters(f1, f21, true)) {
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (justTry) {
|
|
340
|
+
return true;
|
|
341
|
+
}
|
|
342
|
+
for (const f12 of f2[pca2]) {
|
|
343
|
+
tryMergeFilters(f1, f12);
|
|
344
|
+
}
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
347
|
+
else if (pca1 === pca2) {
|
|
348
|
+
if (pca1 === '$and') {
|
|
349
|
+
(0, assert_1.default)(false, '只一个属性的时候不应该用$and');
|
|
350
|
+
}
|
|
351
|
+
else if (pca1 === '$not') {
|
|
352
|
+
// 先not后or 等于先and后not
|
|
353
|
+
if (justTry) {
|
|
354
|
+
return true;
|
|
355
|
+
}
|
|
356
|
+
Object.assign(f1, {
|
|
357
|
+
[pca1]: addFilterSegment(entity, schema, f1[pca1], f2[pca2]),
|
|
358
|
+
});
|
|
359
|
+
return true;
|
|
360
|
+
}
|
|
361
|
+
else if (pca1.startsWith('$')) {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
// 原生属性
|
|
366
|
+
const rel = (0, relation_1.judgeRelation)(schema, entity, pca1);
|
|
367
|
+
if (rel === 1) {
|
|
368
|
+
return tryMergeAttributeValue(f1, f2, pca1, justTry);
|
|
369
|
+
}
|
|
370
|
+
else if (rel === 2) {
|
|
371
|
+
if (justTry) {
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
Object.assign(f1, {
|
|
375
|
+
[pca1]: unionFilterSegment(pca1, schema, f1[pca1], f2[pca2]),
|
|
376
|
+
});
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
else if (typeof rel === 'string') {
|
|
380
|
+
if (justTry) {
|
|
381
|
+
return true;
|
|
382
|
+
}
|
|
383
|
+
Object.assign(f1, {
|
|
384
|
+
[pca1]: unionFilterSegment(rel, schema, f1[pca1], f2[pca2]),
|
|
385
|
+
});
|
|
386
|
+
return true;
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
(0, assert_1.default)(rel instanceof Array);
|
|
390
|
+
// 一对多的子查询,只有子查询的语义算子一样才实施合并
|
|
391
|
+
const sqpOp1 = f1[pca1]['#sqp'] || 'in';
|
|
392
|
+
const sqpOp2 = f2[pca1]['#sqp'] || 'in';
|
|
393
|
+
if (sqpOp1 !== sqpOp2) {
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
if (justTry) {
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
if (sqpOp1 === 'in') {
|
|
400
|
+
Object.assign(f1, {
|
|
401
|
+
[pca1]: Object.assign(unionFilterSegment(rel[0], schema, f1[pca1], f2[pca2]), {
|
|
402
|
+
['#sqp']: sqpOp1,
|
|
403
|
+
})
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
// not in情况子查询变成and
|
|
408
|
+
(0, assert_1.default)(sqpOp1 === 'not in'); // all和not all暂时不支持
|
|
409
|
+
Object.assign(f1, {
|
|
410
|
+
[pca1]: Object.assign(addFilterSegment(rel[0], schema, f1[pca1], f2[pca2]), {
|
|
411
|
+
['#sqp']: sqpOp1,
|
|
412
|
+
})
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return false;
|
|
419
|
+
};
|
|
420
|
+
const addIntoOr = (f) => {
|
|
421
|
+
(0, assert_1.default)(filter);
|
|
422
|
+
if (Object.keys(filter).length === 0) {
|
|
423
|
+
Object.assign(filter, f);
|
|
424
|
+
}
|
|
425
|
+
else if (filter.$or) {
|
|
426
|
+
filter.$or.push(f);
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
filter = {
|
|
430
|
+
$or: [(0, lodash_1.cloneDeep)(filter), f],
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
const addInner = (f) => {
|
|
435
|
+
if (f) {
|
|
436
|
+
if (!filter) {
|
|
437
|
+
filter = (0, lodash_1.cloneDeep)(f);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
if (tryMergeFilters(filter, f)) {
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
addIntoOr(f);
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
filters.forEach(f => addInner(f));
|
|
447
|
+
return filter;
|
|
448
|
+
}
|
|
449
|
+
function combineFilters(entity, schema, filters, union) {
|
|
450
|
+
if (union) {
|
|
451
|
+
return unionFilterSegment(entity, schema, ...filters);
|
|
452
|
+
}
|
|
453
|
+
return addFilterSegment(entity, schema, ...filters);
|
|
454
|
+
}
|
|
455
|
+
exports.combineFilters = combineFilters;
|
|
456
|
+
/**
|
|
457
|
+
* 在以下判断相容或相斥的过程中,相容/相斥的事实标准是:满足两个条件的查询集合是否被包容/互斥,但如果两个filter在逻辑上相容或者相斥,在事实上不一定相容或者相斥
|
|
458
|
+
* 例如:{ a: 1 } 和 { a: { $ne: 1 } } 是明显不相容的查询,但如果数据为空集,则这两个查询并不能否定其相容
|
|
459
|
+
* 我们在处理这类数据时,优先使用逻辑判定的结果(更符合查询本身的期望而非真实数据集),同时也可减少对真实数据集不必要的查询访问
|
|
460
|
+
*/
|
|
461
|
+
/**
|
|
462
|
+
* 判断value1表达的单个属性查询与同属性上value2表达的查询是包容还是相斥
|
|
463
|
+
* 相容即value1所表达的查询结果一定被value2表达的查询结果所包含,例如:
|
|
464
|
+
* value1: {
|
|
465
|
+
* $eq: 12
|
|
466
|
+
* }
|
|
467
|
+
* value2: {
|
|
468
|
+
* $gt: 8,
|
|
469
|
+
* }
|
|
470
|
+
* 此时value1相容value2
|
|
471
|
+
*
|
|
472
|
+
* 相斥即value1所表达的查询结果与value2一定毫无联系,例如:
|
|
473
|
+
* value1: {
|
|
474
|
+
* $gt: 8,
|
|
475
|
+
* }
|
|
476
|
+
* value2: {
|
|
477
|
+
* $lt: 2,
|
|
478
|
+
* }
|
|
479
|
+
*
|
|
480
|
+
*
|
|
481
|
+
* @param value1
|
|
482
|
+
* @param value2
|
|
483
|
+
* @return true代表肯定相容/相斥,false代表肯定不相容/不相斥,undefined代表不能确定
|
|
484
|
+
* @attention: 1)这里的测试不够充分,有些算子之间的相容或相斥可能有遗漏, 2)有新的算子加入需要修改代码
|
|
485
|
+
*/
|
|
486
|
+
function judgeValueRelation(value1, value2, contained) {
|
|
487
|
+
if (typeof value1 === 'object') {
|
|
488
|
+
const attr = Object.keys(value1)[0];
|
|
489
|
+
if (['$gt', '$lt', '$gte', '$lte', '$eq', '$ne', '$startsWith', '$endsWith', '$includes'].includes(attr)) {
|
|
490
|
+
switch (attr) {
|
|
491
|
+
case '$gt': {
|
|
492
|
+
const attr2 = (typeof value2 === 'object') && Object.keys(value2)[0];
|
|
493
|
+
const c = attr2 && ['$gt', '$gte'].includes(attr2) && value2[attr2] <= value1.$gt || (attr2 === '$exists' && value2[attr2] === true);
|
|
494
|
+
const r = (attr2 && (['$lt', '$lte', '$eq'].includes(attr2) && value2[attr2] <= value1.$gt ||
|
|
495
|
+
attr2 === '$in' && value2[attr2] instanceof Array && !((value2[attr2]).find((ele) => typeof ele !== typeof value1.$gt || ele > value1.$gt))) || (attr2 === '$exists' && value2[attr2] === false) || ['string', 'number'].includes(typeof value2) && value2 <= value1.$gt);
|
|
496
|
+
if (contained) {
|
|
497
|
+
if (c) {
|
|
498
|
+
return true;
|
|
499
|
+
}
|
|
500
|
+
else if (r) {
|
|
501
|
+
return false;
|
|
502
|
+
}
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
else {
|
|
506
|
+
if (r) {
|
|
507
|
+
return true;
|
|
508
|
+
}
|
|
509
|
+
return false;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
case '$gte': {
|
|
513
|
+
const attr2 = (typeof value2 === 'object') && Object.keys(value2)[0];
|
|
514
|
+
const c = attr2 && ((['$gte'].includes(attr2) && value2[attr2] <= value1.$gte
|
|
515
|
+
|| ['$gt'].includes(attr2) && value2[attr2] < value1.$gte) || (attr2 === '$exists' && value2[attr2] === true));
|
|
516
|
+
const r = (attr2 && (['$lt'].includes(attr2) && value2[attr2] <= value1.$gte
|
|
517
|
+
|| ['$eq', '$lte'].includes(attr2) && value2[attr2] < value1.gte
|
|
518
|
+
|| attr2 === '$in' && value2[attr2] instanceof Array && !(value2[attr2]).find((ele) => typeof ele !== typeof value1.$gte || ele >= value1.$gte) || (attr2 === '$exists' && value2[attr2] === false))) || (['string', 'number'].includes(typeof value2) && value2 < value1.$gte);
|
|
519
|
+
if (contained) {
|
|
520
|
+
// 包容
|
|
521
|
+
if (c) {
|
|
522
|
+
return true;
|
|
523
|
+
}
|
|
524
|
+
else if (r) {
|
|
525
|
+
return false;
|
|
526
|
+
}
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
if (r) {
|
|
530
|
+
return true;
|
|
531
|
+
}
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
534
|
+
case '$lt': {
|
|
535
|
+
const attr2 = (typeof value2 === 'object') && Object.keys(value2)[0];
|
|
536
|
+
const c = attr2 && (['$lt', '$lte'].includes(attr2) && value2[attr2] >= value1.$lt || attr2 === '$exists' && value2[attr2] === true);
|
|
537
|
+
const r = (attr2 && (['$gt', '$gte', '$eq'].includes(attr2) && value2[attr2] >= value1.$lt
|
|
538
|
+
|| attr2 === '$in' && value2[attr2] instanceof Array && !(value2[attr2]).find((ele) => typeof ele !== typeof value1.$gt || ele < value1.$lt) || (attr2 === '$exists' && value2[attr2] === false))) || (['string', 'number'].includes(typeof value2) && value2 >= value1.$lt);
|
|
539
|
+
if (contained) {
|
|
540
|
+
if (c) {
|
|
541
|
+
return true;
|
|
542
|
+
}
|
|
543
|
+
else if (r) {
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
// 互斥
|
|
549
|
+
if (r) {
|
|
550
|
+
return true;
|
|
551
|
+
}
|
|
552
|
+
return false;
|
|
553
|
+
}
|
|
554
|
+
case '$lte': {
|
|
555
|
+
const attr2 = (typeof value2 === 'object') && Object.keys(value2)[0];
|
|
556
|
+
const c = attr2 && (['$lte'].includes(attr2) && value2[attr2] >= value1.$lte
|
|
557
|
+
|| ['$lt'].includes(attr2) && value2[attr2] > value1.$lte) || (attr2 === '$exists' && value2[attr2] === true);
|
|
558
|
+
const r = (attr2 && (['$gt'].includes(attr2) && value2[attr2] >= value1.$lte
|
|
559
|
+
|| ['$eq', '$gte'].includes(attr2) && value2[attr2] > value1.lte
|
|
560
|
+
|| attr2 === '$in' && value2[attr2] instanceof Array && !(value2[attr2]).find((ele) => typeof ele !== typeof value1.$lte || ele <= value1.$lte) || (attr2 === '$exists' && value2[attr2] === false))) || (['string', 'number'].includes(typeof value2) && value2 > value1.$lte);
|
|
561
|
+
if (contained) {
|
|
562
|
+
// 包容
|
|
563
|
+
if (c) {
|
|
564
|
+
return true;
|
|
565
|
+
}
|
|
566
|
+
else if (r) {
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
// 互斥
|
|
572
|
+
if (r) {
|
|
573
|
+
return true;
|
|
574
|
+
}
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
case '$eq': {
|
|
578
|
+
const attr2 = (typeof value2 === 'object') && Object.keys(value2)[0];
|
|
579
|
+
const c = (attr2 && (attr2 === '$eq' && value2[attr2] === value1.$eq || attr2 === '$ne' && value2[attr2] !== value1.$eq
|
|
580
|
+
|| attr2 === '$gt' && value2[attr2] < value1.$eq || attr2 === '$lt' && value2[attr2] > value1.$eq
|
|
581
|
+
|| attr2 === '$gte' && value2[attr2] <= value1.$eq || attr2 === '$lte' && value2[attr2] >= value1.$eq
|
|
582
|
+
|| attr2 === '$startsWith' && value1.$eq.startsWith(value2[attr2])
|
|
583
|
+
|| attr2 === '$endsWith' && value1.$eq.endsWith(value2[attr2])
|
|
584
|
+
|| attr2 === '$includes' && value1.$eq.includes(value2[attr2])
|
|
585
|
+
|| attr2 === '$in' && value2[attr2] instanceof Array && value2[attr2].includes(value1.$eq)
|
|
586
|
+
|| attr2 === '$nin' && value2[attr2] instanceof Array && !value2[attr2].includes(value1.$eq)
|
|
587
|
+
|| attr2 === '$between' && value2[attr2][0] <= value1.$eq && value2[attr2][1] >= value1.$eq
|
|
588
|
+
|| attr2 === '$exists' && value2[attr2] === true)) || (['string', 'number'].includes(typeof value2) && value2 === value1.$eq);
|
|
589
|
+
const r = (attr2 && (attr2 === '$eq' && value2[attr2] !== value1.$eq || attr2 === '$gt' && value2[attr2] >= value1.$eq
|
|
590
|
+
|| attr2 === '$lt' && value2[attr2] <= value1.$eq
|
|
591
|
+
|| attr2 === '$gte' && value2[attr2] > value1.$eq || attr2 === '$lte' && value2[attr2] < value1.$eq
|
|
592
|
+
|| attr2 === '$startsWith' && !value1.$eq.startsWith(value2[attr2])
|
|
593
|
+
|| attr2 === '$endsWith' && !value1.$eq.endsWith(value2[attr2])
|
|
594
|
+
|| attr2 === '$includes' && !value1.$eq.includes(value2[attr2])
|
|
595
|
+
|| attr2 === '$in' && value2[attr2] instanceof Array && !value2[attr2].includes(value1.$eq)
|
|
596
|
+
|| attr2 === '$between' && (value2[attr2][0] > value1.$eq || value2[attr2][1] < value1.$eq)
|
|
597
|
+
|| attr2 === '$exists' && value2[attr2] === false)) || value2 !== value1.$eq;
|
|
598
|
+
if (contained) {
|
|
599
|
+
// 相容
|
|
600
|
+
if (c) {
|
|
601
|
+
return true;
|
|
602
|
+
}
|
|
603
|
+
else if (r) {
|
|
604
|
+
return false;
|
|
605
|
+
}
|
|
606
|
+
return undefined;
|
|
607
|
+
}
|
|
608
|
+
// 互斥
|
|
609
|
+
if (r) {
|
|
610
|
+
return true;
|
|
611
|
+
}
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
614
|
+
case '$ne': {
|
|
615
|
+
const attr2 = (typeof value2 === 'object') && Object.keys(value2)[0];
|
|
616
|
+
const c = attr2 && attr2 === '$ne' && value2[attr2] === value1.$ne;
|
|
617
|
+
const r = (attr2 === '$eq' && value2[attr2] === value1.$ne) || value2 === value1.$ne;
|
|
618
|
+
if (contained) {
|
|
619
|
+
if (c) {
|
|
620
|
+
return true;
|
|
621
|
+
}
|
|
622
|
+
else if (r) {
|
|
623
|
+
return false;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
// 互斥
|
|
627
|
+
if (r) {
|
|
628
|
+
return true;
|
|
629
|
+
}
|
|
630
|
+
return false;
|
|
631
|
+
}
|
|
632
|
+
case '$startsWith': {
|
|
633
|
+
const attr2 = (typeof value2 === 'object') && Object.keys(value2)[0];
|
|
634
|
+
const c = attr2 === '$startsWith' && typeof (value2[attr2]) === 'string'
|
|
635
|
+
&& value1.$startsWith.startsWith(value2[attr2]);
|
|
636
|
+
const r = attr2 === '$startsWith' && typeof (value2[attr2]) === 'string'
|
|
637
|
+
&& !value1.$startsWith.startsWith(value2[attr2]) && !value2[attr2].startsWith(value1.$startsWith)
|
|
638
|
+
|| attr2 === '$eq' && !value2[attr2].startsWith(value1.$startsWith)
|
|
639
|
+
|| typeof value2 === 'string' && !value2.startsWith(value1.$startsWith);
|
|
640
|
+
// 这里似乎还有更多情况,但实际中不可能跑到,不处理了
|
|
641
|
+
if (contained) {
|
|
642
|
+
if (c) {
|
|
643
|
+
return true;
|
|
644
|
+
}
|
|
645
|
+
else if (r) {
|
|
646
|
+
return false;
|
|
647
|
+
}
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
// 互斥
|
|
651
|
+
if (r) {
|
|
652
|
+
return true;
|
|
653
|
+
}
|
|
654
|
+
return false;
|
|
655
|
+
}
|
|
656
|
+
case '$endsWith': {
|
|
657
|
+
const attr2 = (typeof value2 === 'object') && Object.keys(value2)[0];
|
|
658
|
+
const c = attr2 === '$endsWith' && typeof (value2[attr2]) === 'string'
|
|
659
|
+
&& value1.$endsWith.endsWith(value2[attr2]);
|
|
660
|
+
const r = (attr2 === '$endsWith' && typeof (value2[attr2]) === 'string'
|
|
661
|
+
&& !value1.$endsWith.endsWith(value2[attr2]) && !value2[attr2].endsWith(value1.$endsWith)
|
|
662
|
+
|| attr2 === '$eq' && !value2[attr2].endsWith(value1.$endsWith)) || typeof value2 === 'string' && !value2.endsWith(value1.$endsWith);
|
|
663
|
+
if (contained) {
|
|
664
|
+
// 相容
|
|
665
|
+
if (c) {
|
|
666
|
+
return true;
|
|
667
|
+
}
|
|
668
|
+
else if (r) {
|
|
669
|
+
return false;
|
|
670
|
+
}
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
if (r) {
|
|
674
|
+
return true;
|
|
675
|
+
}
|
|
676
|
+
return false;
|
|
677
|
+
}
|
|
678
|
+
case '$includes': {
|
|
679
|
+
const attr2 = (typeof value2 === 'object') && Object.keys(value2)[0];
|
|
680
|
+
const c = (attr2 && ['$includes', '$startsWith', '$endsWith'].includes(attr2)
|
|
681
|
+
&& typeof (value2[attr2]) === 'string'
|
|
682
|
+
&& (value2[attr2]).includes(value1.$includes)) || typeof value2 === 'string' && value2.includes(value1.$includes);
|
|
683
|
+
const r = (attr2 === '$eq' && !value2[attr2].includes(value1.$includes)
|
|
684
|
+
|| attr2 === '$in' && value2[attr2] instanceof Array && !value2[attr2].find((ele) => ele.includes(value1.$includes))) || typeof value2 === 'string' && !value2.includes(value1.$includes);
|
|
685
|
+
if (contained) {
|
|
686
|
+
if (c) {
|
|
687
|
+
return true;
|
|
688
|
+
}
|
|
689
|
+
else if (r) {
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
if (r) {
|
|
695
|
+
return true;
|
|
696
|
+
}
|
|
697
|
+
return false;
|
|
698
|
+
}
|
|
699
|
+
default: {
|
|
700
|
+
(0, assert_1.default)(false, `不能处理的算子「${attr}」`);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
else if (['$exists'].includes(attr)) {
|
|
705
|
+
const attr2 = (typeof value2 === 'object') && Object.keys(value2)[0];
|
|
706
|
+
const c = attr2 === '$exists' && value2[attr2] === value1.$exists;
|
|
707
|
+
const r = attr2 === '$exists' && value2[attr2] !== value1.$exists;
|
|
708
|
+
if (contained) {
|
|
709
|
+
if (c) {
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
712
|
+
else if (r) {
|
|
713
|
+
return false;
|
|
714
|
+
}
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
if (r) {
|
|
718
|
+
return true;
|
|
719
|
+
}
|
|
720
|
+
return false;
|
|
721
|
+
}
|
|
722
|
+
else if (['$in', '$nin', '$between'].includes(attr)) {
|
|
723
|
+
switch (attr) {
|
|
724
|
+
case '$in': {
|
|
725
|
+
(0, assert_1.default)(value1.$in instanceof Array);
|
|
726
|
+
const attr2 = (typeof value2 === 'object') && Object.keys(value2)[0];
|
|
727
|
+
let c = (attr2 === '$in' && value2[attr2] instanceof Array && (0, lodash_1.difference)(value1.$in, value2[attr2]).length === 0) || (attr2 === '$nin' && value2[attr2] instanceof Array && (0, lodash_1.intersection)(value1.$in, value2[attr2]).length === 0) || (attr2 === '$exists' && value2[attr2] === true);
|
|
728
|
+
if (!c && attr2 && ['$gt', '$gte', '$lt', '$lte', '$between'].includes(attr2)) {
|
|
729
|
+
let min33, max33;
|
|
730
|
+
value1.$in.forEach((ele) => {
|
|
731
|
+
if (!min33 || min33 > ele) {
|
|
732
|
+
min33 = ele;
|
|
733
|
+
}
|
|
734
|
+
if (!max33 || max33 < ele) {
|
|
735
|
+
max33 = ele;
|
|
736
|
+
}
|
|
737
|
+
});
|
|
738
|
+
c = attr2 === '$gt' && value2[attr2] < min33 || attr2 === '$gte' && value2[attr2] <= min33
|
|
739
|
+
|| attr2 === '$lt' && value2[attr2] > max33 || attr2 === '$lte' && value2[attr2] >= max33
|
|
740
|
+
|| attr2 === '$between' && value2[attr2][0] < min33 && value2[attr2][1] > max33;
|
|
741
|
+
}
|
|
742
|
+
let r = (attr2 === '$in' && (0, lodash_1.intersection)(value2[attr2], value1.$in).length === 0) || (attr2 === '$eq' && !value1.$in.includes(value2[attr2])) || (attr2 === '$exists' && value2[attr2] === false) || (!value1.$in.includes(value2));
|
|
743
|
+
if (!r && attr2 && ['$gt', '$gte', '$lt', '$lte', '$between'].includes(attr2)) {
|
|
744
|
+
let min44, max44;
|
|
745
|
+
value1.$in.forEach((ele) => {
|
|
746
|
+
if (!min44 || min44 > ele) {
|
|
747
|
+
min44 = ele;
|
|
748
|
+
}
|
|
749
|
+
if (!max44 || max44 < ele) {
|
|
750
|
+
max44 = ele;
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
r = attr2 === '$gt' && value2[attr2] >= max44 || attr2 === '$gte' && value2[attr2] > max44
|
|
754
|
+
|| attr2 === '$lt' && value2[attr2] <= min44 || attr2 === '$lte' && value2[attr2] < min44
|
|
755
|
+
|| attr2 === '$between' && (value2[attr2][0] > max44 || value2[attr2][1] < min44);
|
|
756
|
+
}
|
|
757
|
+
if (contained) {
|
|
758
|
+
// 相容
|
|
759
|
+
if (c) {
|
|
760
|
+
return true;
|
|
761
|
+
}
|
|
762
|
+
else if (r) {
|
|
763
|
+
return false;
|
|
764
|
+
}
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
// 相斥
|
|
768
|
+
if (r) {
|
|
769
|
+
return true;
|
|
770
|
+
}
|
|
771
|
+
return false;
|
|
772
|
+
}
|
|
773
|
+
case '$nin': {
|
|
774
|
+
(0, assert_1.default)(value1.$nin instanceof Array);
|
|
775
|
+
const attr2 = (typeof value2 === 'object') && Object.keys(value2)[0];
|
|
776
|
+
const c = attr2 && (attr2 === '$nin' && value2[attr2] instanceof Array && (0, lodash_1.intersection)(value2[attr2], value1.$nin).length === 0
|
|
777
|
+
|| attr2 === '$ne' && value1.$nin.includes(value2[attr2]));
|
|
778
|
+
const r = attr2 && (attr2 === '$in' && value2[attr2] instanceof Array && (0, lodash_1.intersection)(value2[attr2], value1.$nin).length > 0) || value1.$nin.includes(value2);
|
|
779
|
+
if (contained) {
|
|
780
|
+
// 相容
|
|
781
|
+
if (c) {
|
|
782
|
+
return true;
|
|
783
|
+
}
|
|
784
|
+
else if (r) {
|
|
785
|
+
return false;
|
|
786
|
+
}
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
if (r) {
|
|
790
|
+
return true;
|
|
791
|
+
}
|
|
792
|
+
return false;
|
|
793
|
+
}
|
|
794
|
+
case '$between': {
|
|
795
|
+
(0, assert_1.default)(value1.$between instanceof Array);
|
|
796
|
+
const attr2 = (typeof value2 === 'object') && Object.keys(value2)[0];
|
|
797
|
+
const c = attr2 && (attr2 === '$between' && value2[attr2][0] <= value1.$between[0] && value2[attr2][1] >= value1.$between[1]
|
|
798
|
+
|| attr2 === '$gt' && value2[attr2] < value1.$between[0] || attr2 === '$gte' && value2[attr2] <= value1.$between[0]
|
|
799
|
+
|| attr2 === '$lt' && value2[attr2] > value1.$between[1] || attr2 === '$lte' && value2[attr2] >= value1.$between[1]
|
|
800
|
+
|| attr2 === '$exists' && value2[attr2] === true);
|
|
801
|
+
const r = attr2 && (attr2 === '$between' && (value2[attr2][0] > value1.$between[1] || value2[attr2][1] < value1.$between[0])
|
|
802
|
+
|| attr2 === '$gt' && value2[attr2] > value1.$between[1] || attr2 === '$gte' && value2[attr2] >= value1.$between[1]
|
|
803
|
+
|| attr2 === '$lt' && value2[attr2] < value1.$between[0] || attr2 === '$lte' && value2[attr2] <= value1.$between[0]
|
|
804
|
+
|| attr2 === '$eq' && (value2[attr2] > value1.$between[1] || value2[attr2] < value1.$between[0])
|
|
805
|
+
|| attr2 === '$exists' && value2[attr2] === false
|
|
806
|
+
|| attr2 === '$in' && value2[attr2] instanceof Array && !value2[attr2].find((ele) => ele >= value1.$between[0] && ele <= value1.$between[1])) || value2 > value1.$between[1] || value2 < value1.$between[0];
|
|
807
|
+
if (contained) {
|
|
808
|
+
if (c) {
|
|
809
|
+
return true;
|
|
810
|
+
}
|
|
811
|
+
else if (r) {
|
|
812
|
+
return false;
|
|
813
|
+
}
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
// 相斥
|
|
817
|
+
if (r) {
|
|
818
|
+
return true;
|
|
819
|
+
}
|
|
820
|
+
return false;
|
|
821
|
+
}
|
|
822
|
+
default: {
|
|
823
|
+
(0, assert_1.default)(false, `暂不支持的算子${attr}`);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
else {
|
|
828
|
+
console.warn(`「judgeValueRelation」未知算子「${attr}」`);
|
|
829
|
+
return false;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
else {
|
|
833
|
+
// value1是一个等值查询
|
|
834
|
+
const attr2 = (typeof value2 === 'object') && Object.keys(value2)[0];
|
|
835
|
+
const c = attr2 === '$eq' && value2[attr2] === value1 || attr2 === '$ne' && value2[attr2] !== value1
|
|
836
|
+
|| attr2 === '$gt' && value2[attr2] < value1 || attr2 === '$lt' && value2[attr2] > value1
|
|
837
|
+
|| attr2 === '$gte' && value2[attr2] <= value1 || attr2 === '$lte' && value2[attr2] >= value1
|
|
838
|
+
|| attr2 === '$startsWith' && value1.startsWith(value2[attr2])
|
|
839
|
+
|| attr2 === '$endsWith' && value1.endsWith(value2[attr2])
|
|
840
|
+
|| attr2 === '$includes' && value1.includes(value2[attr2])
|
|
841
|
+
|| attr2 === '$in' && value2[attr2] instanceof Array && value2[attr2].includes(value1)
|
|
842
|
+
|| attr2 === '$nin' && value2[attr2] instanceof Array && !value2[attr2].includes(value1)
|
|
843
|
+
|| attr2 === '$between' && value2[attr2][0] <= value1 && value2[attr2][1] >= value1
|
|
844
|
+
|| attr2 === '$exists' && value2[attr2] === true
|
|
845
|
+
|| value2 === value1;
|
|
846
|
+
const r = attr2 === '$eq' && value2[attr2] !== value1 || attr2 === '$gt' && value2[attr2] >= value1
|
|
847
|
+
|| attr2 === '$lt' && value2[attr2] <= value1
|
|
848
|
+
|| attr2 === '$gte' && value2[attr2] > value1 || attr2 === '$lte' && value2[attr2] < value1
|
|
849
|
+
|| attr2 === '$startsWith' && !value1.startsWith(value2[attr2])
|
|
850
|
+
|| attr2 === '$endsWith' && !value1.endsWith(value2[attr2])
|
|
851
|
+
|| attr2 === '$includes' && !value1.includes(value2[attr2])
|
|
852
|
+
|| attr2 === '$in' && value2[attr2] instanceof Array && !value2[attr2].includes(value1)
|
|
853
|
+
|| attr2 === '$between' && (value2[attr2][0] > value1 || value2[attr2][1] < value1)
|
|
854
|
+
|| attr2 === '$exists' && value2[attr2] === false
|
|
855
|
+
|| typeof value2 === typeof value1 && value2 !== value1;
|
|
856
|
+
if (contained) {
|
|
857
|
+
// 相容
|
|
858
|
+
if (c) {
|
|
859
|
+
return true;
|
|
860
|
+
}
|
|
861
|
+
else if (r) {
|
|
862
|
+
return false;
|
|
863
|
+
}
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
// 互斥
|
|
867
|
+
if (r) {
|
|
868
|
+
return true;
|
|
869
|
+
}
|
|
870
|
+
return false;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
exports.judgeValueRelation = judgeValueRelation;
|
|
874
|
+
/**
|
|
875
|
+
* 判断filter条件对compared条件上的attr键值的条件是否相容或相斥
|
|
876
|
+
* @param entity
|
|
877
|
+
* @param schema
|
|
878
|
+
* @param attr
|
|
879
|
+
* @param filter
|
|
880
|
+
* @param compared
|
|
881
|
+
* @param contained
|
|
882
|
+
* @returns 返回true说明肯定相容(相斥),返回false说明肯定不相容(相斥),返回undefined说明无法判定相容(相斥),返回DeducedFilterCombination说明需要进一步判断此推断的条件
|
|
883
|
+
*/
|
|
884
|
+
function judgeFilterSingleAttrRelation(entity, schema, attr, filter, compared, contained) {
|
|
885
|
+
const comparedFilterAttrValue = compared[attr];
|
|
886
|
+
const orDeducedFilters = [];
|
|
887
|
+
if (attr === 'entityId') {
|
|
888
|
+
// entityId不可能作为查询条件单独存在
|
|
889
|
+
(0, assert_1.default)(compared.hasOwnProperty('entity'));
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
for (const attr2 in filter) {
|
|
893
|
+
if (['$and', '$or', '$not'].includes(attr2)) {
|
|
894
|
+
switch (attr2) {
|
|
895
|
+
case '$and':
|
|
896
|
+
case '$or': {
|
|
897
|
+
const andDeducedFilters = [];
|
|
898
|
+
const logicQueries = filter[attr2];
|
|
899
|
+
const results = logicQueries.map((logicQuery) => judgeFilterSingleAttrRelation(entity, schema, attr, logicQuery, compared, contained));
|
|
900
|
+
// 如果filter的多个算子是and关系,则只要有一个包含此条件就是包含,只要有一个与此条件相斥就是相斥
|
|
901
|
+
// 如果filter的多个算子是or关系,则必须所有的条件都包含此条件才是包含,必须所有的条件都与此条件相斥才是相斥
|
|
902
|
+
for (const r of results) {
|
|
903
|
+
if (r === true && attr2 === '$and') {
|
|
904
|
+
return true;
|
|
905
|
+
}
|
|
906
|
+
if (r === false && attr2 === '$or') {
|
|
907
|
+
return false;
|
|
908
|
+
}
|
|
909
|
+
if (r === undefined) {
|
|
910
|
+
if (attr2 === '$or') {
|
|
911
|
+
// or有一个不能确定就返回不确定
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
if (typeof r === 'object') {
|
|
916
|
+
if (attr2 === '$and') {
|
|
917
|
+
orDeducedFilters.push(r);
|
|
918
|
+
}
|
|
919
|
+
else {
|
|
920
|
+
(0, assert_1.default)(attr2 === '$or');
|
|
921
|
+
andDeducedFilters.push(r);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
if (andDeducedFilters.length > 0) {
|
|
926
|
+
orDeducedFilters.push({
|
|
927
|
+
$and: andDeducedFilters,
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
break;
|
|
931
|
+
}
|
|
932
|
+
case '$not': {
|
|
933
|
+
/*
|
|
934
|
+
* 若filter的not条件被comparedFilterAttrValue条件包容,则说明两者互斥
|
|
935
|
+
* filter包容comparedFilterAttrValue条件暂时无法由其not条件推论出来
|
|
936
|
+
*/
|
|
937
|
+
if (!contained) {
|
|
938
|
+
const logicQuery = filter[attr2];
|
|
939
|
+
const r = judgeFilterRelation(entity, schema, { [attr]: comparedFilterAttrValue }, logicQuery, true);
|
|
940
|
+
if (r === true) {
|
|
941
|
+
return true;
|
|
942
|
+
}
|
|
943
|
+
else if (typeof r === 'object') {
|
|
944
|
+
orDeducedFilters.push(r);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
break;
|
|
948
|
+
}
|
|
949
|
+
default: {
|
|
950
|
+
(0, assert_1.default)(false);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
else if (attr2.toLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
|
|
955
|
+
// 相当于缩小了filter的查询结果集,若其它条件能判断出来filter与compared[attr]相容或相斥,此条件无影响
|
|
956
|
+
}
|
|
957
|
+
else if (attr2.toLowerCase() === '$text') {
|
|
958
|
+
// 相当于缩小了filter的查询结果集,若其它条件能判断出来filter与compared[attr]相容或相斥,此条件无影响
|
|
959
|
+
}
|
|
960
|
+
else {
|
|
961
|
+
const rel = (0, relation_1.judgeRelation)(schema, entity, attr2);
|
|
962
|
+
if (attr === attr2) {
|
|
963
|
+
if (rel === 1) {
|
|
964
|
+
const r = judgeValueRelation(filter[attr2], comparedFilterAttrValue, contained);
|
|
965
|
+
if (typeof r === 'boolean') {
|
|
966
|
+
return r;
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
else if (rel === 2) {
|
|
970
|
+
const r = judgeFilterRelation(attr2, schema, filter[attr2], comparedFilterAttrValue, contained);
|
|
971
|
+
if (typeof r === 'boolean') {
|
|
972
|
+
return r;
|
|
973
|
+
}
|
|
974
|
+
else if (typeof r === 'object') {
|
|
975
|
+
orDeducedFilters.push(r);
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
else if (typeof rel === 'string') {
|
|
979
|
+
const r = judgeFilterRelation(rel, schema, filter[attr2], comparedFilterAttrValue, contained);
|
|
980
|
+
if (typeof r === 'boolean') {
|
|
981
|
+
return r;
|
|
982
|
+
}
|
|
983
|
+
else if (typeof r === 'object') {
|
|
984
|
+
orDeducedFilters.push(r);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
else {
|
|
988
|
+
// todo 一对多如何判定?
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
else if (rel === 2 && attr === 'entity' && comparedFilterAttrValue === attr2 && compared.hasOwnProperty('entityId')) {
|
|
992
|
+
// compared指定了entity和entityId,而filter指定了该entity上的查询条件,此时转而比较此entity上的filter
|
|
993
|
+
const r = judgeFilterRelation(attr2, schema, filter[attr2], {
|
|
994
|
+
id: compared.entityId
|
|
995
|
+
}, contained);
|
|
996
|
+
if (typeof r === 'boolean') {
|
|
997
|
+
return r;
|
|
998
|
+
}
|
|
999
|
+
else if (typeof r === 'object') {
|
|
1000
|
+
orDeducedFilters.push(r);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
else if (typeof rel === 'string' && attr === `${attr2}Id`) {
|
|
1004
|
+
// compared指定了外键,而filter指定了该外键对象上的查询条件,此时转而比较此entity上的filter
|
|
1005
|
+
const r = judgeFilterRelation(rel, schema, filter[attr2], {
|
|
1006
|
+
id: comparedFilterAttrValue
|
|
1007
|
+
}, contained);
|
|
1008
|
+
if (typeof r === 'boolean') {
|
|
1009
|
+
return r;
|
|
1010
|
+
}
|
|
1011
|
+
else if (typeof r === 'object') {
|
|
1012
|
+
orDeducedFilters.push(r);
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
else {
|
|
1016
|
+
const rel2 = (0, relation_1.judgeRelation)(schema, entity, attr);
|
|
1017
|
+
if (rel2 === 2 && attr2 === 'entity' && filter[attr2] === attr && filter.hasOwnProperty('entityId')) {
|
|
1018
|
+
// filter限制了外键范围,而compared指定了该外键对象上的查询条件, 此时转而比较此entity上的filter
|
|
1019
|
+
const r = judgeFilterRelation(attr, schema, {
|
|
1020
|
+
id: filter.entityId,
|
|
1021
|
+
}, comparedFilterAttrValue, contained);
|
|
1022
|
+
if (typeof r === 'boolean') {
|
|
1023
|
+
return r;
|
|
1024
|
+
}
|
|
1025
|
+
else if (typeof r === 'object') {
|
|
1026
|
+
orDeducedFilters.push(r);
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
else if (typeof rel2 === 'string' && attr2 === `${attr}Id`) {
|
|
1030
|
+
// filter限制了外键范围,而compared指定了该外键对象上的查询条件, 此时转而比较此entity上的filter
|
|
1031
|
+
const r = judgeFilterRelation(rel2, schema, {
|
|
1032
|
+
id: filter[attr2],
|
|
1033
|
+
}, comparedFilterAttrValue, contained);
|
|
1034
|
+
if (typeof r === 'boolean') {
|
|
1035
|
+
return r;
|
|
1036
|
+
}
|
|
1037
|
+
else if (typeof r === 'object') {
|
|
1038
|
+
orDeducedFilters.push(r);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
if (orDeducedFilters.length > 0) {
|
|
1045
|
+
return {
|
|
1046
|
+
$or: orDeducedFilters,
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
// 到这里说明无法直接判断此attr上的相容或者相斥,也无法把判定推断到更深层的算子之上
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
/** 判断filter条件对compared条件是否相容或相斥
|
|
1053
|
+
* @param entity
|
|
1054
|
+
* @param schema
|
|
1055
|
+
* @param filter
|
|
1056
|
+
* @param compared
|
|
1057
|
+
* @param contained: true代表判定filter包容compared(filter的查询结果是compared查询结果的子集), false代表判定filter与compared相斥(filter的查询结果与compared没有交集)
|
|
1058
|
+
* @returns 返回true说明肯定相容(相斥),返回false说明无法判定相容(相斥),返回DeducedFilterCombination说明需要进一步判断此推断的条件
|
|
1059
|
+
*/
|
|
1060
|
+
function judgeFilterRelation(entity, schema, filter, compared, contained) {
|
|
1061
|
+
const totalAndDeducedFilters = [];
|
|
1062
|
+
const totalOrDeducedFilters = [];
|
|
1063
|
+
const uncertainAttributes = [];
|
|
1064
|
+
const sureAttributes = []; // 对包容查询,肯定此属性可包容;对相斥查询,肯定此属性不相斥
|
|
1065
|
+
for (let attr in compared) {
|
|
1066
|
+
let result = undefined;
|
|
1067
|
+
const deducedCombinations = [];
|
|
1068
|
+
if (['$and', '$or', '$not'].includes(attr)) {
|
|
1069
|
+
switch (attr) {
|
|
1070
|
+
case '$and': {
|
|
1071
|
+
const logicQueries = compared[attr];
|
|
1072
|
+
const results = logicQueries.map((logicQuery) => judgeFilterRelation(entity, schema, filter, logicQuery, contained));
|
|
1073
|
+
const andDeducedFilters = [];
|
|
1074
|
+
const orDeducedFilters = [];
|
|
1075
|
+
for (const r of results) {
|
|
1076
|
+
if (contained) {
|
|
1077
|
+
// 如果是包容关系,需要全部被包容,有一个被证伪就已经失败了
|
|
1078
|
+
if (r === false) {
|
|
1079
|
+
result = false;
|
|
1080
|
+
break;
|
|
1081
|
+
}
|
|
1082
|
+
else if (r === undefined) {
|
|
1083
|
+
// 有一个无法判断就放弃
|
|
1084
|
+
andDeducedFilters.splice(0, andDeducedFilters.length);
|
|
1085
|
+
result = undefined;
|
|
1086
|
+
break;
|
|
1087
|
+
}
|
|
1088
|
+
else if (typeof r === 'object') {
|
|
1089
|
+
andDeducedFilters.push(r);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
else {
|
|
1093
|
+
(0, assert_1.default)(!contained);
|
|
1094
|
+
// 如果是相斥关系,只要和一个相斥就可以,有一个被证实就成功了
|
|
1095
|
+
if (r === true) {
|
|
1096
|
+
orDeducedFilters.splice(0, orDeducedFilters.length);
|
|
1097
|
+
result = true;
|
|
1098
|
+
break;
|
|
1099
|
+
}
|
|
1100
|
+
else if (typeof r === 'object') {
|
|
1101
|
+
orDeducedFilters.push(r);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
if (andDeducedFilters.length > 0) {
|
|
1106
|
+
deducedCombinations.push({
|
|
1107
|
+
$and: andDeducedFilters,
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
if (orDeducedFilters.length > 0) {
|
|
1111
|
+
deducedCombinations.push({
|
|
1112
|
+
$or: orDeducedFilters,
|
|
1113
|
+
});
|
|
1114
|
+
}
|
|
1115
|
+
break;
|
|
1116
|
+
}
|
|
1117
|
+
case '$or': {
|
|
1118
|
+
const logicQueries = compared[attr];
|
|
1119
|
+
const results = logicQueries.map((logicQuery) => judgeFilterRelation(entity, schema, filter, logicQuery, contained));
|
|
1120
|
+
const andDeducedFilters = [];
|
|
1121
|
+
const orDeducedFilters = [];
|
|
1122
|
+
for (const r of results) {
|
|
1123
|
+
if (contained) {
|
|
1124
|
+
// 如果是包容关系,只要包容一个(是其查询子集)就可以
|
|
1125
|
+
if (r === true) {
|
|
1126
|
+
orDeducedFilters.splice(0, orDeducedFilters.length);
|
|
1127
|
+
result = true;
|
|
1128
|
+
break;
|
|
1129
|
+
}
|
|
1130
|
+
else if (typeof r === 'object') {
|
|
1131
|
+
// 这里不能把or下降到所有的查询中去分别判定,有可能此条件需要多个compared中的情况来共同满足
|
|
1132
|
+
// orDeducedFilters.push(r);
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
else {
|
|
1136
|
+
(0, assert_1.default)(!contained);
|
|
1137
|
+
// 如果是相斥关系,必须和每一个都相斥
|
|
1138
|
+
if (r === false) {
|
|
1139
|
+
result = false;
|
|
1140
|
+
break;
|
|
1141
|
+
}
|
|
1142
|
+
else if (r === undefined) {
|
|
1143
|
+
// 有一个无法判断就放弃
|
|
1144
|
+
andDeducedFilters.splice(0, andDeducedFilters.length);
|
|
1145
|
+
result = undefined;
|
|
1146
|
+
break;
|
|
1147
|
+
}
|
|
1148
|
+
else if (typeof r === 'object') {
|
|
1149
|
+
andDeducedFilters.push(r);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
if (andDeducedFilters.length > 0) {
|
|
1154
|
+
deducedCombinations.push({
|
|
1155
|
+
$and: andDeducedFilters,
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1158
|
+
if (orDeducedFilters.length > 0) {
|
|
1159
|
+
deducedCombinations.push({
|
|
1160
|
+
$or: orDeducedFilters,
|
|
1161
|
+
});
|
|
1162
|
+
}
|
|
1163
|
+
break;
|
|
1164
|
+
}
|
|
1165
|
+
case '$not': {
|
|
1166
|
+
/**
|
|
1167
|
+
* 若filter与compared not所定义的部分相斥,则filter与conditionalFilter相容
|
|
1168
|
+
* 若filter将compared not所定义的部分包容,则filter与conditionalFilter相斥
|
|
1169
|
+
*/
|
|
1170
|
+
const logicQuery = compared[attr];
|
|
1171
|
+
if (contained) {
|
|
1172
|
+
const r = judgeFilterRelation(entity, schema, filter, logicQuery, false);
|
|
1173
|
+
if (r === true) {
|
|
1174
|
+
result = true;
|
|
1175
|
+
}
|
|
1176
|
+
else if (typeof r === 'object') {
|
|
1177
|
+
deducedCombinations.push(r);
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
else {
|
|
1181
|
+
const r = judgeFilterRelation(entity, schema, filter, logicQuery, true);
|
|
1182
|
+
if (r === true) {
|
|
1183
|
+
result = true;
|
|
1184
|
+
}
|
|
1185
|
+
else if (typeof r === 'object') {
|
|
1186
|
+
deducedCombinations.push(r);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
break;
|
|
1190
|
+
}
|
|
1191
|
+
default: {
|
|
1192
|
+
throw new Error(`暂不支持的逻辑算子${attr}`);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
else if (attr.toLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
|
|
1197
|
+
// 相当于缩小了compared查询结果,如果是判定相斥,对结果无影响,如果是判定相容,则认为无法判定,
|
|
1198
|
+
if (contained) {
|
|
1199
|
+
result = undefined;
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
else if (attr.toLowerCase() === '$text') {
|
|
1203
|
+
// 相当于缩小了compared查询结果,如果是判定相斥,对结果无影响,如果是判定相容,则认为无法判定,
|
|
1204
|
+
if (contained) {
|
|
1205
|
+
result = undefined;
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
else {
|
|
1209
|
+
const r = judgeFilterSingleAttrRelation(entity, schema, attr, filter, compared, contained);
|
|
1210
|
+
if (typeof r === 'object') {
|
|
1211
|
+
deducedCombinations.push(r);
|
|
1212
|
+
}
|
|
1213
|
+
else {
|
|
1214
|
+
result = r;
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
if (contained) {
|
|
1218
|
+
// 相容必须compared中的每个属性都被相容
|
|
1219
|
+
if (result === true) {
|
|
1220
|
+
sureAttributes.push(attr);
|
|
1221
|
+
}
|
|
1222
|
+
else if (result === false) {
|
|
1223
|
+
return false;
|
|
1224
|
+
}
|
|
1225
|
+
else if (deducedCombinations.length > 0) {
|
|
1226
|
+
totalAndDeducedFilters.push(...deducedCombinations);
|
|
1227
|
+
}
|
|
1228
|
+
else {
|
|
1229
|
+
// 判定不了,也推断不了
|
|
1230
|
+
uncertainAttributes.push(attr);
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
else {
|
|
1234
|
+
// 相斥只要有一个被肻定就可以返回true了
|
|
1235
|
+
if (result === true) {
|
|
1236
|
+
return true;
|
|
1237
|
+
}
|
|
1238
|
+
else if (result === false) {
|
|
1239
|
+
sureAttributes.push(attr);
|
|
1240
|
+
}
|
|
1241
|
+
else if (deducedCombinations.length > 0) {
|
|
1242
|
+
totalOrDeducedFilters.push(...deducedCombinations);
|
|
1243
|
+
}
|
|
1244
|
+
else {
|
|
1245
|
+
// 判定不了,也推断不了
|
|
1246
|
+
uncertainAttributes.push(attr);
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
if (contained) {
|
|
1251
|
+
if (sureAttributes.length === Object.keys(compared).length) {
|
|
1252
|
+
return true;
|
|
1253
|
+
}
|
|
1254
|
+
if (uncertainAttributes.length > 0) {
|
|
1255
|
+
// 有属性无法界定,此时只能拿本行去查询
|
|
1256
|
+
totalAndDeducedFilters.push({
|
|
1257
|
+
entity,
|
|
1258
|
+
filter: combineFilters(entity, schema, [filter, {
|
|
1259
|
+
$not: (0, lodash_1.pick)(compared, uncertainAttributes),
|
|
1260
|
+
}]),
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
return {
|
|
1264
|
+
$and: totalAndDeducedFilters,
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
else {
|
|
1268
|
+
if (sureAttributes.length === Object.keys(compared).length) {
|
|
1269
|
+
return false;
|
|
1270
|
+
}
|
|
1271
|
+
// uncertainAttributes中是无法判定的属性,和filter合并之后(同时满足)的查询结果如果不为空说明不互斥
|
|
1272
|
+
if (uncertainAttributes.length > 0) {
|
|
1273
|
+
totalOrDeducedFilters.push({
|
|
1274
|
+
entity,
|
|
1275
|
+
filter: combineFilters(entity, schema, [filter, (0, lodash_1.pick)(compared, uncertainAttributes)]),
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
return {
|
|
1279
|
+
$or: totalOrDeducedFilters,
|
|
1280
|
+
};
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
/**
|
|
1284
|
+
*
|
|
1285
|
+
* 判断filter是否包含contained中的查询条件,即filter查询的结果一定是contained查询结果的子集
|
|
1286
|
+
* filter = {
|
|
1287
|
+
* a: 1
|
|
1288
|
+
* b: 2,
|
|
1289
|
+
* c: 3,
|
|
1290
|
+
* },
|
|
1291
|
+
* conditionalFilter = {
|
|
1292
|
+
* a: 1
|
|
1293
|
+
* }
|
|
1294
|
+
* 则包含
|
|
1295
|
+
* @param entity
|
|
1296
|
+
* @param schema
|
|
1297
|
+
* @param filter
|
|
1298
|
+
* @param contained
|
|
1299
|
+
* @returns
|
|
1300
|
+
*/
|
|
1301
|
+
function contains(entity, schema, filter, contained) {
|
|
1302
|
+
(0, assert_1.default)(filter);
|
|
1303
|
+
(0, assert_1.default)(contained);
|
|
1304
|
+
return judgeFilterRelation(entity, schema, filter, contained, true);
|
|
1305
|
+
// return false;
|
|
1306
|
+
}
|
|
1307
|
+
/**
|
|
1308
|
+
* 判断filter1和filter2是否相斥,即filter1和filter2查询的结果一定没有交集
|
|
1309
|
+
* filter1 = {
|
|
1310
|
+
* a: 2
|
|
1311
|
+
* },
|
|
1312
|
+
* filter2 = {
|
|
1313
|
+
* a: 1
|
|
1314
|
+
* }
|
|
1315
|
+
* 则包含
|
|
1316
|
+
* @param entity
|
|
1317
|
+
* @param schema
|
|
1318
|
+
* @param filter
|
|
1319
|
+
* @param conditionalFilter
|
|
1320
|
+
*/
|
|
1321
|
+
function repel(entity, schema, filter1, filter2) {
|
|
1322
|
+
(0, assert_1.default)(filter1);
|
|
1323
|
+
(0, assert_1.default)(filter2);
|
|
1324
|
+
/**
|
|
1325
|
+
* 现在的算法检查相斥有一种情况,若filter1被filter2相容,可以判断出来是false,但如果filter2被filter1相容则检查不出来
|
|
1326
|
+
* filter1 = {
|
|
1327
|
+
* id: 'user',
|
|
1328
|
+
* }
|
|
1329
|
+
* filter2 = {
|
|
1330
|
+
id: 'user',
|
|
1331
|
+
$$seq$$: 'xc',
|
|
1332
|
+
* }
|
|
1333
|
+
* 这种情况就检查不出来,所以再反向判断一次是否相容
|
|
1334
|
+
*/
|
|
1335
|
+
const repelled = judgeFilterRelation(entity, schema, filter1, filter2, false);
|
|
1336
|
+
if (typeof repelled === 'boolean') {
|
|
1337
|
+
return repelled;
|
|
1338
|
+
}
|
|
1339
|
+
if (contains(entity, schema, filter2, filter1) === true) {
|
|
1340
|
+
return false;
|
|
1341
|
+
}
|
|
1342
|
+
return repelled;
|
|
1343
|
+
}
|
|
1344
|
+
/**
|
|
1345
|
+
* 从filter中判断是否有确定的id对象,如果有则返回这些id,没有返回空数组
|
|
1346
|
+
* @param filter
|
|
1347
|
+
* @returns
|
|
1348
|
+
*/
|
|
1349
|
+
function getRelevantIds(filter) {
|
|
1350
|
+
let ids;
|
|
1351
|
+
let idsAnd;
|
|
1352
|
+
let idsOr;
|
|
1353
|
+
if (!filter) {
|
|
1354
|
+
return [];
|
|
1355
|
+
}
|
|
1356
|
+
// 因为要准确判定id,如果有其它的过滤条件,可能会使实际处理的行数少于id指向的行数,只能返回空数组
|
|
1357
|
+
const attrs = Object.keys(filter);
|
|
1358
|
+
if ((0, lodash_1.intersection)(attrs, ['id', '$and', '$or']).length > 3) {
|
|
1359
|
+
return [];
|
|
1360
|
+
}
|
|
1361
|
+
if (filter?.$and) {
|
|
1362
|
+
const idss = filter.$and.map((ele) => getRelevantIds(ele));
|
|
1363
|
+
// and有一个不能判断就返回空集
|
|
1364
|
+
if (idss.find(ele => ele.length === 0)) {
|
|
1365
|
+
return [];
|
|
1366
|
+
}
|
|
1367
|
+
idsAnd = (0, lodash_1.intersection)(...idss);
|
|
1368
|
+
}
|
|
1369
|
+
if (filter?.$or) {
|
|
1370
|
+
const idss = filter.$or.map((ele) => getRelevantIds(ele));
|
|
1371
|
+
// or有一个不能判断就返回空集
|
|
1372
|
+
if (idss.find(ele => ele.length === 0)) {
|
|
1373
|
+
return [];
|
|
1374
|
+
}
|
|
1375
|
+
idsOr = (0, lodash_1.union)(...idss);
|
|
1376
|
+
}
|
|
1377
|
+
if (filter?.id) {
|
|
1378
|
+
if (typeof filter.id === 'string') {
|
|
1379
|
+
ids = [filter.id];
|
|
1380
|
+
}
|
|
1381
|
+
else if (filter.id?.$eq) {
|
|
1382
|
+
ids = [filter.id.$eq];
|
|
1383
|
+
}
|
|
1384
|
+
else if (filter.id?.$in && filter.id.$in instanceof Array) {
|
|
1385
|
+
ids = filter.id.$in;
|
|
1386
|
+
}
|
|
1387
|
+
else {
|
|
1388
|
+
return [];
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
// 三者如果有基一,直接返回,如果大于一返回intersection
|
|
1392
|
+
if (!ids && !idsAnd && !idsOr) {
|
|
1393
|
+
return [];
|
|
1394
|
+
}
|
|
1395
|
+
let result = (ids || idsAnd || idsOr);
|
|
1396
|
+
if (ids) {
|
|
1397
|
+
result = (0, lodash_1.intersection)(result, ids);
|
|
1398
|
+
}
|
|
1399
|
+
if (idsAnd) {
|
|
1400
|
+
result = (0, lodash_1.intersection)(result, idsAnd);
|
|
1401
|
+
}
|
|
1402
|
+
if (idsOr) {
|
|
1403
|
+
result = (0, lodash_1.intersection)(result, idsOr);
|
|
1404
|
+
}
|
|
1405
|
+
return result;
|
|
1406
|
+
}
|
|
1407
|
+
exports.getRelevantIds = getRelevantIds;
|
|
1408
|
+
/**
|
|
1409
|
+
* 判断两个过滤条件是否完全一致
|
|
1410
|
+
* @param entity
|
|
1411
|
+
* @param schema
|
|
1412
|
+
* @param filter1
|
|
1413
|
+
* @param filter2
|
|
1414
|
+
*/
|
|
1415
|
+
function same(entity, schema, filter1, filter2) {
|
|
1416
|
+
// 当前只需要判断是不是id相等就行了,在runningTree的operation合并的时间使用
|
|
1417
|
+
if (!filter1 || !filter1.id || Object.keys(filter1).length > 1 || !filter2 || !filter2.id || Object.keys(filter2).length > 1) {
|
|
1418
|
+
return false;
|
|
1419
|
+
}
|
|
1420
|
+
return filter1.id === filter2.id;
|
|
1421
|
+
}
|
|
1422
|
+
exports.same = same;
|
|
1423
|
+
/**
|
|
1424
|
+
* 寻找在树形结构中满足条件的数据行的上层数据
|
|
1425
|
+
* 例如在area表中,如果“杭州市”满足这一条件,则希望查到更高层的“浙江省”和“中国”,即可构造出满足条件的filter
|
|
1426
|
+
* @param entity
|
|
1427
|
+
* @param parentKey parentId属性名
|
|
1428
|
+
* @param filter 查询当前行的条件
|
|
1429
|
+
* @param level
|
|
1430
|
+
*/
|
|
1431
|
+
function makeTreeAncestorFilter(entity, parentKey, filter, level = 1, includeAll, includeSelf) {
|
|
1432
|
+
(0, assert_1.default)(level >= 0);
|
|
1433
|
+
let idInFilters = [];
|
|
1434
|
+
if (includeSelf) {
|
|
1435
|
+
idInFilters.push(filter);
|
|
1436
|
+
}
|
|
1437
|
+
let currentLevelInFilter = filter;
|
|
1438
|
+
while (level > 0) {
|
|
1439
|
+
currentLevelInFilter = {
|
|
1440
|
+
id: {
|
|
1441
|
+
$in: {
|
|
1442
|
+
entity,
|
|
1443
|
+
data: {
|
|
1444
|
+
[parentKey]: 1,
|
|
1445
|
+
},
|
|
1446
|
+
filter: currentLevelInFilter,
|
|
1447
|
+
}
|
|
1448
|
+
},
|
|
1449
|
+
};
|
|
1450
|
+
if (includeAll) {
|
|
1451
|
+
idInFilters.push(currentLevelInFilter);
|
|
1452
|
+
}
|
|
1453
|
+
level--;
|
|
1454
|
+
}
|
|
1455
|
+
;
|
|
1456
|
+
if (includeAll) {
|
|
1457
|
+
return {
|
|
1458
|
+
$or: idInFilters,
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
return currentLevelInFilter;
|
|
1462
|
+
}
|
|
1463
|
+
exports.makeTreeAncestorFilter = makeTreeAncestorFilter;
|
|
1464
|
+
/**
|
|
1465
|
+
* 寻找在树形结构中满足条件的数据行的下层数据
|
|
1466
|
+
* 例如在area表中,如果“杭州市”满足这一条件,则希望查到更低层的“西湖区”,即可构造出满足条件的filter
|
|
1467
|
+
* @param entity
|
|
1468
|
+
* @param parentKey parentId属性名
|
|
1469
|
+
* @param filter 查询当前行的条件
|
|
1470
|
+
* @param level
|
|
1471
|
+
*/
|
|
1472
|
+
function makeTreeDescendantFilter(entity, parentKey, filter, level = 1, includeAll, includeSelf) {
|
|
1473
|
+
(0, assert_1.default)(level >= 0);
|
|
1474
|
+
(0, assert_1.default)(parentKey.endsWith('Id'));
|
|
1475
|
+
const parentKeyRef = parentKey.slice(0, parentKey.length - 2);
|
|
1476
|
+
let idInFilters = [];
|
|
1477
|
+
if (includeSelf) {
|
|
1478
|
+
idInFilters.push(filter);
|
|
1479
|
+
}
|
|
1480
|
+
let currentLevelInFilter = filter;
|
|
1481
|
+
while (level > 0) {
|
|
1482
|
+
currentLevelInFilter = {
|
|
1483
|
+
[parentKeyRef]: currentLevelInFilter,
|
|
1484
|
+
};
|
|
1485
|
+
if (includeAll) {
|
|
1486
|
+
idInFilters.push(currentLevelInFilter);
|
|
1487
|
+
}
|
|
1488
|
+
level--;
|
|
1489
|
+
}
|
|
1490
|
+
;
|
|
1491
|
+
if (includeAll) {
|
|
1492
|
+
return {
|
|
1493
|
+
$or: idInFilters,
|
|
1494
|
+
};
|
|
1495
|
+
}
|
|
1496
|
+
return currentLevelInFilter;
|
|
1497
|
+
}
|
|
1498
|
+
exports.makeTreeDescendantFilter = makeTreeDescendantFilter;
|
|
1499
|
+
function checkDeduceFilters(dfc, context) {
|
|
1500
|
+
const { $and, $or } = dfc;
|
|
1501
|
+
if ($and) {
|
|
1502
|
+
(0, assert_1.default)(!$or);
|
|
1503
|
+
const andResult = $and.map((ele) => {
|
|
1504
|
+
if (ele.hasOwnProperty('entity')) {
|
|
1505
|
+
const ele2 = ele;
|
|
1506
|
+
return context.count(ele2.entity, {
|
|
1507
|
+
filter: ele2.filter
|
|
1508
|
+
}, { ignoreAttrMiss: true });
|
|
1509
|
+
}
|
|
1510
|
+
const ele2 = ele;
|
|
1511
|
+
return checkDeduceFilters(ele2, context);
|
|
1512
|
+
});
|
|
1513
|
+
// and 意味着只要有一个条件失败就返回false
|
|
1514
|
+
if (andResult.find(ele => ele instanceof Promise)) {
|
|
1515
|
+
return Promise.all(andResult).then((ar) => {
|
|
1516
|
+
for (const ele of ar) {
|
|
1517
|
+
if (ele === false || typeof ele === 'number' && ele > 0) {
|
|
1518
|
+
return false;
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
return true;
|
|
1522
|
+
});
|
|
1523
|
+
}
|
|
1524
|
+
for (const ele of andResult) {
|
|
1525
|
+
if (ele === false || typeof ele === 'number' && ele > 0) {
|
|
1526
|
+
return false;
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
return true;
|
|
1530
|
+
}
|
|
1531
|
+
(0, assert_1.default)($or);
|
|
1532
|
+
const orResult = $or.map((ele) => {
|
|
1533
|
+
if (ele.hasOwnProperty('entity')) {
|
|
1534
|
+
const ele2 = ele;
|
|
1535
|
+
return context.count(ele2.entity, {
|
|
1536
|
+
filter: ele2.filter
|
|
1537
|
+
}, { ignoreAttrMiss: true });
|
|
1538
|
+
}
|
|
1539
|
+
const ele2 = ele;
|
|
1540
|
+
return checkDeduceFilters(ele2, context);
|
|
1541
|
+
});
|
|
1542
|
+
// or只要有一个条件通过就返回true
|
|
1543
|
+
if (orResult.find(ele => ele instanceof Promise)) {
|
|
1544
|
+
return Promise.all(orResult).then((or) => {
|
|
1545
|
+
for (const ele of or) {
|
|
1546
|
+
if (ele === true || ele === 0) {
|
|
1547
|
+
return true;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
return false;
|
|
1551
|
+
});
|
|
1552
|
+
}
|
|
1553
|
+
for (const ele of orResult) {
|
|
1554
|
+
if (ele === true || ele === 0) {
|
|
1555
|
+
return true;
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
return false;
|
|
1559
|
+
}
|
|
1560
|
+
/**
|
|
1561
|
+
* 检查filter是否包含contained(filter查询的数据是contained查询数据的子集)
|
|
1562
|
+
* @param entity
|
|
1563
|
+
* @param context
|
|
1564
|
+
* @param contained
|
|
1565
|
+
* @param filter
|
|
1566
|
+
* @param dataCompare
|
|
1567
|
+
* @returns
|
|
1568
|
+
*/
|
|
1569
|
+
function checkFilterContains(entity, context, contained, filter, dataCompare, warningOnDataCompare) {
|
|
1570
|
+
if (!filter) {
|
|
1571
|
+
throw new types_1.OakRowInconsistencyException();
|
|
1572
|
+
}
|
|
1573
|
+
const schema = context.getSchema();
|
|
1574
|
+
const result = contains(entity, schema, filter, contained);
|
|
1575
|
+
if (typeof result === 'boolean') {
|
|
1576
|
+
return result;
|
|
1577
|
+
}
|
|
1578
|
+
if (dataCompare) {
|
|
1579
|
+
if (warningOnDataCompare) {
|
|
1580
|
+
console.warn(`data compare on ${entity}, please optimize`);
|
|
1581
|
+
}
|
|
1582
|
+
return checkDeduceFilters(result, context);
|
|
1583
|
+
}
|
|
1584
|
+
return false;
|
|
1585
|
+
}
|
|
1586
|
+
exports.checkFilterContains = checkFilterContains;
|
|
1587
|
+
function checkFilterRepel(entity, context, filter1, filter2, dataCompare, warningOnDataCompare) {
|
|
1588
|
+
if (!filter2) {
|
|
1589
|
+
throw new types_1.OakRowInconsistencyException();
|
|
1590
|
+
}
|
|
1591
|
+
const schema = context.getSchema();
|
|
1592
|
+
const result = repel(entity, schema, filter2, filter1);
|
|
1593
|
+
if (typeof result === 'boolean') {
|
|
1594
|
+
return result;
|
|
1595
|
+
}
|
|
1596
|
+
if (dataCompare) {
|
|
1597
|
+
if (warningOnDataCompare) {
|
|
1598
|
+
console.warn(`data compare on ${entity}, please optimize`);
|
|
1599
|
+
}
|
|
1600
|
+
return checkDeduceFilters(result, context);
|
|
1601
|
+
}
|
|
1602
|
+
return false;
|
|
1603
|
+
}
|
|
1604
|
+
exports.checkFilterRepel = checkFilterRepel;
|
|
1605
|
+
/**
|
|
1606
|
+
* 有的场景下将filter当成非结构化属性存储,又想支持对其查询,此时必须将查询的filter进行转换,处理其中$开头的escape
|
|
1607
|
+
* 只要filter是查询数据的标准子集,查询应当能返回true
|
|
1608
|
+
* @param filter
|
|
1609
|
+
*/
|
|
1610
|
+
function translateFilterToObjectPredicate(filter) {
|
|
1611
|
+
const copyInner = (orig, dest) => {
|
|
1612
|
+
for (const key in orig) {
|
|
1613
|
+
const value = orig[key];
|
|
1614
|
+
const key2 = key.startsWith('$') ? `.${key}` : key;
|
|
1615
|
+
if (typeof value === 'object' && !(value instanceof Array)) {
|
|
1616
|
+
dest[key2] = {};
|
|
1617
|
+
copyInner(value, dest[key2]);
|
|
1618
|
+
}
|
|
1619
|
+
else {
|
|
1620
|
+
dest[key2] = value;
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
};
|
|
1624
|
+
const translated = {};
|
|
1625
|
+
copyInner(filter, translated);
|
|
1626
|
+
return translated;
|
|
1627
|
+
}
|
|
1628
|
+
exports.translateFilterToObjectPredicate = translateFilterToObjectPredicate;
|
|
1629
|
+
/* export function getCascadeEntityFilter<ED extends EntityDict & BaseEntityDict, T extends keyof ED>(
|
|
1630
|
+
filter: NonNullable<ED[T]['Selection']['filter']>,
|
|
1631
|
+
attr: keyof NonNullable<ED[T]['Selection']['filter']>
|
|
1632
|
+
): ED[keyof ED]['Selection']['filter'] {
|
|
1633
|
+
const filters: ED[keyof ED]['Selection']['filter'][] = [];
|
|
1634
|
+
if (filter![attr]) {
|
|
1635
|
+
assert(typeof filter![attr] === 'object');
|
|
1636
|
+
filters.push(filter![attr]);
|
|
1637
|
+
}
|
|
1638
|
+
if (filter.$and) {
|
|
1639
|
+
filter.$and.forEach(
|
|
1640
|
+
(ele: NonNullable<ED[T]['Selection']['filter']>) => {
|
|
1641
|
+
const f2 = getCascadeEntityFilter(ele, attr);
|
|
1642
|
+
if (f2) {
|
|
1643
|
+
filters.push(f2)
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
);
|
|
1647
|
+
}
|
|
1648
|
+
if (filters.length > 0) {
|
|
1649
|
+
return combineFilters(filters);
|
|
1650
|
+
}
|
|
1651
|
+
} */
|