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