@finos/legend-query-builder 4.1.15 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. package/lib/components/filter/QueryBuilderFilterPanel.d.ts +6 -1
  2. package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
  3. package/lib/components/filter/QueryBuilderFilterPanel.js +189 -13
  4. package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
  5. package/lib/index.css +2 -2
  6. package/lib/index.css.map +1 -1
  7. package/lib/package.json +1 -1
  8. package/lib/stores/QueryBuilderStateHashUtils.d.ts +1 -0
  9. package/lib/stores/QueryBuilderStateHashUtils.d.ts.map +1 -1
  10. package/lib/stores/QueryBuilderStateHashUtils.js +1 -0
  11. package/lib/stores/QueryBuilderStateHashUtils.js.map +1 -1
  12. package/lib/stores/filter/QueryBuilderFilterOperator.d.ts +1 -1
  13. package/lib/stores/filter/QueryBuilderFilterOperator.d.ts.map +1 -1
  14. package/lib/stores/filter/QueryBuilderFilterOperator.js.map +1 -1
  15. package/lib/stores/filter/QueryBuilderFilterState.d.ts +16 -5
  16. package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
  17. package/lib/stores/filter/QueryBuilderFilterState.js +78 -18
  18. package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
  19. package/lib/stores/filter/QueryBuilderFilterStateBuilder.d.ts.map +1 -1
  20. package/lib/stores/filter/QueryBuilderFilterStateBuilder.js +125 -2
  21. package/lib/stores/filter/QueryBuilderFilterStateBuilder.js.map +1 -1
  22. package/lib/stores/filter/QueryBuilderFilterValueSpecificationBuilder.d.ts.map +1 -1
  23. package/lib/stores/filter/QueryBuilderFilterValueSpecificationBuilder.js +62 -3
  24. package/lib/stores/filter/QueryBuilderFilterValueSpecificationBuilder.js.map +1 -1
  25. package/lib/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.d.ts +1 -1
  26. package/lib/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.d.ts.map +1 -1
  27. package/lib/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.js +12 -192
  28. package/lib/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.js.map +1 -1
  29. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.d.ts +2 -2
  30. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.d.ts.map +1 -1
  31. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.js +4 -4
  32. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.js.map +1 -1
  33. package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.d.ts +2 -2
  34. package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.d.ts.map +1 -1
  35. package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.js +4 -4
  36. package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.js.map +1 -1
  37. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.d.ts +2 -2
  38. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.d.ts.map +1 -1
  39. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.js +4 -4
  40. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.js.map +1 -1
  41. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.d.ts +1 -1
  42. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.d.ts.map +1 -1
  43. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.js +2 -2
  44. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.js.map +1 -1
  45. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.d.ts +1 -1
  46. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.d.ts.map +1 -1
  47. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.js +2 -2
  48. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.js.map +1 -1
  49. package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.d.ts +2 -2
  50. package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.d.ts.map +1 -1
  51. package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.js +4 -4
  52. package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.js.map +1 -1
  53. package/lib/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.d.ts +2 -2
  54. package/lib/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.d.ts.map +1 -1
  55. package/lib/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.js +4 -4
  56. package/lib/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.js.map +1 -1
  57. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.d.ts +1 -1
  58. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.d.ts.map +1 -1
  59. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.js +2 -2
  60. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.js.map +1 -1
  61. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.d.ts +1 -1
  62. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.d.ts.map +1 -1
  63. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.js +2 -2
  64. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.js.map +1 -1
  65. package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.d.ts +2 -2
  66. package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.d.ts.map +1 -1
  67. package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.js +4 -4
  68. package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.js.map +1 -1
  69. package/package.json +1 -1
  70. package/src/components/filter/QueryBuilderFilterPanel.tsx +355 -24
  71. package/src/stores/QueryBuilderStateHashUtils.ts +1 -0
  72. package/src/stores/filter/QueryBuilderFilterOperator.ts +1 -0
  73. package/src/stores/filter/QueryBuilderFilterState.ts +115 -27
  74. package/src/stores/filter/QueryBuilderFilterStateBuilder.ts +244 -0
  75. package/src/stores/filter/QueryBuilderFilterValueSpecificationBuilder.ts +94 -1
  76. package/src/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.ts +37 -377
  77. package/src/stores/filter/operators/QueryBuilderFilterOperator_Contain.ts +7 -1
  78. package/src/stores/filter/operators/QueryBuilderFilterOperator_EndWith.ts +7 -1
  79. package/src/stores/filter/operators/QueryBuilderFilterOperator_Equal.ts +7 -1
  80. package/src/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.ts +2 -0
  81. package/src/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.ts +2 -0
  82. package/src/stores/filter/operators/QueryBuilderFilterOperator_In.ts +7 -1
  83. package/src/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.ts +7 -1
  84. package/src/stores/filter/operators/QueryBuilderFilterOperator_LessThan.ts +2 -0
  85. package/src/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.ts +2 -0
  86. package/src/stores/filter/operators/QueryBuilderFilterOperator_StartWith.ts +7 -1
@@ -19,217 +19,36 @@ import {
19
19
  extractElementNameFromPath,
20
20
  matchFunctionName,
21
21
  LambdaFunctionInstanceValue,
22
- VariableExpression,
23
22
  AbstractPropertyExpression,
24
23
  SimpleFunctionExpression,
25
- Multiplicity,
24
+ LambdaFunction,
26
25
  } from '@finos/legend-graph';
27
26
  import {
28
27
  guaranteeType,
29
28
  guaranteeNonNullable,
30
29
  assertTrue,
31
- generateEnumerableNameFromToken,
32
30
  } from '@finos/legend-shared';
33
31
  import {
34
32
  FilterConditionState,
35
33
  type QueryBuilderFilterState,
36
34
  } from '../QueryBuilderFilterState.js';
37
35
  import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '../../../graph/QueryBuilderMetaModelConst.js';
38
- import {
39
- buildGenericLambdaFunctionInstanceValue,
40
- simplifyValueExpression,
41
- } from '../../QueryBuilderValueSpecificationHelper.js';
36
+ import { simplifyValueExpression } from '../../QueryBuilderValueSpecificationHelper.js';
42
37
  import type { QueryBuilderFilterOperator } from '../QueryBuilderFilterOperator.js';
43
38
  import { buildPropertyExpressionChain } from '../../QueryBuilderValueSpecificationBuilderHelper.js';
44
39
 
45
- const getPropertyExpressionChainVariable = (
46
- propertyExpression: AbstractPropertyExpression,
47
- ): VariableExpression => {
48
- let currentExpression: ValueSpecification = propertyExpression;
49
- while (currentExpression instanceof AbstractPropertyExpression) {
50
- currentExpression = guaranteeNonNullable(
51
- currentExpression.parametersValues[0],
52
- );
53
- // Take care of chains of subtype (a pattern that is not useful, but we want to support and rectify)
54
- // $x.employees->subType(@Person)->subType(@Staff)
55
- while (
56
- currentExpression instanceof SimpleFunctionExpression &&
57
- matchFunctionName(
58
- currentExpression.functionName,
59
- QUERY_BUILDER_SUPPORTED_FUNCTIONS.SUBTYPE,
60
- )
61
- ) {
62
- currentExpression = guaranteeNonNullable(
63
- currentExpression.parametersValues[0],
64
- );
65
- }
66
- }
67
- return guaranteeType(currentExpression, VariableExpression);
68
- };
69
-
70
- const buildFilterConditionExpressionWithExists = (
71
- filterConditionState: FilterConditionState,
72
- operatorFunctionFullPath: string,
73
- ): ValueSpecification => {
74
- assertTrue(
75
- filterConditionState.propertyExpressionState.requiresExistsHandling,
76
- );
77
- // 1. Decompose property expression
78
- const expressions: (AbstractPropertyExpression | SimpleFunctionExpression)[] =
79
- [];
80
- let currentPropertyExpression: ValueSpecification =
81
- buildPropertyExpressionChain(
82
- filterConditionState.propertyExpressionState.propertyExpression,
83
- filterConditionState.propertyExpressionState.queryBuilderState,
84
- filterConditionState.filterState.lambdaParameterName,
85
- );
86
- while (
87
- currentPropertyExpression instanceof AbstractPropertyExpression ||
88
- (currentPropertyExpression instanceof SimpleFunctionExpression &&
89
- matchFunctionName(
90
- currentPropertyExpression.functionName,
91
- QUERY_BUILDER_SUPPORTED_FUNCTIONS.SUBTYPE,
92
- ))
93
- ) {
94
- let exp: AbstractPropertyExpression | SimpleFunctionExpression;
95
- if (currentPropertyExpression instanceof SimpleFunctionExpression) {
96
- exp = new SimpleFunctionExpression(
97
- extractElementNameFromPath(QUERY_BUILDER_SUPPORTED_FUNCTIONS.SUBTYPE),
98
- );
99
- } else {
100
- exp = new AbstractPropertyExpression('');
101
- exp.func = currentPropertyExpression.func;
102
- }
103
- // NOTE: we must retain the rest of the parameters as those are derived property parameters
104
- exp.parametersValues =
105
- currentPropertyExpression.parametersValues.length > 1
106
- ? currentPropertyExpression.parametersValues.slice(1)
107
- : [];
108
- expressions.push(exp);
109
- currentPropertyExpression = guaranteeNonNullable(
110
- currentPropertyExpression.parametersValues[0],
111
- );
112
- }
113
- const rootVariable = guaranteeType(
114
- currentPropertyExpression,
115
- VariableExpression,
116
- );
117
-
118
- // 2. Traverse the list of decomposed property expression backward, every time we encounter a property of
119
- // multiplicity many, create a new property expression and keep track of it to later form the lambda chain
120
- const existsLambdaParamNames = [
121
- ...filterConditionState.existsLambdaParamNames,
122
- ];
123
- const existsLambdaPropertyChains: ValueSpecification[] = [rootVariable];
124
- let currentParamNameIndex = 0;
125
-
126
- for (let i = expressions.length - 1; i >= 0; --i) {
127
- const exp = expressions[i] as
128
- | AbstractPropertyExpression
129
- | SimpleFunctionExpression;
130
- // just keep adding to the property chain
131
- exp.parametersValues.unshift(
132
- existsLambdaPropertyChains[
133
- existsLambdaPropertyChains.length - 1
134
- ] as ValueSpecification,
135
- );
136
- existsLambdaPropertyChains[existsLambdaPropertyChains.length - 1] = exp;
137
- // ... but if the property is of multiplicity multiple, start a new property chain
138
- if (
139
- exp instanceof AbstractPropertyExpression &&
140
- (exp.func.value.multiplicity.upperBound === undefined ||
141
- exp.func.value.multiplicity.upperBound > 1)
142
- ) {
143
- // NOTE: we need to find/generate the property chain variable name
144
- // here, by doing this, we try our best to respect original/user-input variable name
145
- if (currentParamNameIndex > existsLambdaParamNames.length - 1) {
146
- existsLambdaParamNames.push(
147
- generateEnumerableNameFromToken(
148
- existsLambdaParamNames,
149
- filterConditionState.filterState.lambdaParameterName,
150
- ),
151
- );
152
- assertTrue(currentParamNameIndex === existsLambdaParamNames.length - 1);
153
- }
154
- existsLambdaPropertyChains.push(
155
- new VariableExpression(
156
- existsLambdaParamNames[currentParamNameIndex] as string,
157
- Multiplicity.ONE,
158
- ),
159
- );
160
- currentParamNameIndex++;
161
- }
162
- }
163
-
164
- // 3. Build each property chain into an exists() simple function expression
165
- const simpleFunctionExpressions: SimpleFunctionExpression[] = [];
166
- for (let i = 0; i < existsLambdaPropertyChains.length - 1; ++i) {
167
- const simpleFunctionExpression = new SimpleFunctionExpression(
168
- extractElementNameFromPath(QUERY_BUILDER_SUPPORTED_FUNCTIONS.EXISTS),
169
- );
170
- simpleFunctionExpression.parametersValues.push(
171
- existsLambdaPropertyChains[i] as ValueSpecification,
172
- );
173
- simpleFunctionExpressions.push(simpleFunctionExpression);
174
- }
175
- // build the leaf simple function expression which uses the operator
176
- const operatorEpression = new SimpleFunctionExpression(
177
- extractElementNameFromPath(operatorFunctionFullPath),
178
- );
179
- operatorEpression.parametersValues.push(
180
- existsLambdaPropertyChains[
181
- existsLambdaPropertyChains.length - 1
182
- ] as ValueSpecification,
183
- );
184
- // NOTE: there are simple operators which do not require any params (e.g. isEmpty)
185
- if (filterConditionState.value) {
186
- operatorEpression.parametersValues.push(filterConditionState.value);
187
- }
188
- simpleFunctionExpressions.push(operatorEpression);
189
-
190
- // 4. Build the exists() lambda chain
191
- assertTrue(simpleFunctionExpressions.length >= 2);
192
- for (let i = simpleFunctionExpressions.length - 2; i >= 0; --i) {
193
- const currentSFE = simpleFunctionExpressions[i] as SimpleFunctionExpression;
194
- const childSFE = simpleFunctionExpressions[
195
- i + 1
196
- ] as SimpleFunctionExpression;
197
- // build child SFE lambda
198
- const _existsLambdaVariable = childSFE.parametersValues[0];
199
- const existsLambdaVariable =
200
- _existsLambdaVariable instanceof AbstractPropertyExpression
201
- ? getPropertyExpressionChainVariable(_existsLambdaVariable)
202
- : guaranteeType(_existsLambdaVariable, VariableExpression);
203
- const existsLambda = buildGenericLambdaFunctionInstanceValue(
204
- existsLambdaVariable.name,
205
- [childSFE],
206
- filterConditionState.filterState.queryBuilderState.graphManagerState
207
- .graph,
208
- );
209
- // add the child SFE lambda to the current SFE parameters
210
- currentSFE.parametersValues.push(existsLambda);
211
- }
212
-
213
- return simpleFunctionExpressions[0] as SimpleFunctionExpression;
214
- };
215
-
216
40
  export const buildFilterConditionExpression = (
217
41
  filterConditionState: FilterConditionState,
218
42
  operatorFunctionFullPath: string,
43
+ lambdaParameterName?: string | undefined,
219
44
  ): ValueSpecification => {
220
- if (filterConditionState.propertyExpressionState.requiresExistsHandling) {
221
- return buildFilterConditionExpressionWithExists(
222
- filterConditionState,
223
- operatorFunctionFullPath,
224
- );
225
- }
226
45
  const expression = new SimpleFunctionExpression(
227
46
  extractElementNameFromPath(operatorFunctionFullPath),
228
47
  );
229
48
  const propertyExpression = buildPropertyExpressionChain(
230
49
  filterConditionState.propertyExpressionState.propertyExpression,
231
50
  filterConditionState.propertyExpressionState.queryBuilderState,
232
- filterConditionState.filterState.lambdaParameterName,
51
+ lambdaParameterName ?? filterConditionState.filterState.lambdaParameterName,
233
52
  );
234
53
  expression.parametersValues.push(guaranteeNonNullable(propertyExpression));
235
54
  // NOTE: there are simple operators which do not require any params (e.g. isEmpty)
@@ -239,182 +58,6 @@ export const buildFilterConditionExpression = (
239
58
  return expression;
240
59
  };
241
60
 
242
- /**
243
- * Handling exists() lambda found in the filter condition expression.
244
- * The general approach for handling exists() is we will flat out the chain
245
- * of exists() expressions into a normal filter condition state.
246
- *
247
- * When we build the condition function expression from the filter condition state,
248
- * we walk the property expression chain, find property with multiplitiy upper bound
249
- * other than 1 and create an exists() lambda there
250
- *
251
- * NOTE: to ensure we respect user's choice of variable name, as we build the state
252
- * we record the lambda parameter names, so we can use those while re-building the function
253
- * If for some reason, this list is stale, we can start adding our own parameter names
254
- */
255
- const buildFilterConditionStateWithExists = (
256
- filterState: QueryBuilderFilterState,
257
- parentExpression: SimpleFunctionExpression,
258
- operatorFunctionFullPath: string,
259
- ): [FilterConditionState | undefined, SimpleFunctionExpression | undefined] => {
260
- if (
261
- matchFunctionName(
262
- parentExpression.functionName,
263
- QUERY_BUILDER_SUPPORTED_FUNCTIONS.EXISTS,
264
- )
265
- ) {
266
- // 1. Decompose the exists() lambda chain into property expression chains
267
- const existsLambdaParameterNames: string[] = [];
268
-
269
- // `existsLambdaExpressions` should be a list of `AbstractPropertyExpression`
270
- // e.g. |Firm.all()->filter(x|$x.employees->exists(x_1|$x_1->subType(@Develper).id->exists(x_2|$x_2 == 1))
271
- // In the first exists() lambda, `$x_1->subType(@Develper).id` is an `AbstractPropertyExpression`.
272
- const existsLambdaExpressions: AbstractPropertyExpression[] = [];
273
- let mainFilterExpression: SimpleFunctionExpression = parentExpression;
274
- while (
275
- matchFunctionName(
276
- mainFilterExpression.functionName,
277
- QUERY_BUILDER_SUPPORTED_FUNCTIONS.EXISTS,
278
- )
279
- ) {
280
- const existsLambda = guaranteeNonNullable(
281
- guaranteeType(
282
- mainFilterExpression.parametersValues[1],
283
- LambdaFunctionInstanceValue,
284
- ).values[0],
285
- `Can't process exists() expression: exists() lambda is missing`,
286
- );
287
- assertTrue(
288
- existsLambda.expressionSequence.length === 1,
289
- `Can't process exists() expression: exists() lambda body should hold an expression`,
290
- );
291
- mainFilterExpression = guaranteeType(
292
- existsLambda.expressionSequence[0],
293
- SimpleFunctionExpression,
294
- `Can't process exists() expression: exists() lambda body should hold an expression`,
295
- );
296
-
297
- // record the lambda parameter name
298
- assertTrue(
299
- existsLambda.functionType.parameters.length === 1,
300
- `Can't process exists() expression: exists() lambda should have 1 parameter`,
301
- );
302
- existsLambdaParameterNames.push(
303
- guaranteeType(
304
- existsLambda.functionType.parameters[0],
305
- VariableExpression,
306
- `Can't process exists() expression: exists() lambda should have 1 parameter`,
307
- ).name,
308
- );
309
-
310
- // record the lambda property expression
311
- if (
312
- mainFilterExpression.parametersValues[0] instanceof
313
- AbstractPropertyExpression
314
- ) {
315
- existsLambdaExpressions.push(mainFilterExpression.parametersValues[0]);
316
- }
317
- }
318
- // NOTE: make sure that the inner most function expression is the one we support
319
- if (
320
- !matchFunctionName(
321
- mainFilterExpression.functionName,
322
- operatorFunctionFullPath,
323
- )
324
- ) {
325
- return [undefined, undefined];
326
- }
327
-
328
- // 2. Build the property expression
329
- const initialPropertyExpression = guaranteeType(
330
- parentExpression.parametersValues[0],
331
- AbstractPropertyExpression,
332
- );
333
- let flattenedPropertyExpressionChain = new AbstractPropertyExpression('');
334
- flattenedPropertyExpressionChain.func = initialPropertyExpression.func;
335
- flattenedPropertyExpressionChain.parametersValues = [
336
- ...initialPropertyExpression.parametersValues,
337
- ];
338
-
339
- for (const expression of existsLambdaExpressions) {
340
- // when rebuilding the property expression chain, disregard the initial variable that starts the chain
341
- const expressions: (
342
- | AbstractPropertyExpression
343
- | SimpleFunctionExpression
344
- )[] = [];
345
- let currentExpression: ValueSpecification = expression;
346
- while (
347
- currentExpression instanceof AbstractPropertyExpression ||
348
- (currentExpression instanceof SimpleFunctionExpression &&
349
- matchFunctionName(
350
- currentExpression.functionName,
351
- QUERY_BUILDER_SUPPORTED_FUNCTIONS.SUBTYPE,
352
- ))
353
- ) {
354
- if (currentExpression instanceof SimpleFunctionExpression) {
355
- const functionExpression = new SimpleFunctionExpression(
356
- extractElementNameFromPath(
357
- QUERY_BUILDER_SUPPORTED_FUNCTIONS.SUBTYPE,
358
- ),
359
- );
360
- functionExpression.parametersValues.unshift(
361
- guaranteeNonNullable(currentExpression.parametersValues[1]),
362
- );
363
- expressions.push(functionExpression);
364
- } else if (currentExpression instanceof AbstractPropertyExpression) {
365
- const propertyExpression = new AbstractPropertyExpression('');
366
- propertyExpression.func = currentExpression.func;
367
- // NOTE: we must retain the rest of the parameters as those are derived property parameters
368
- propertyExpression.parametersValues =
369
- currentExpression.parametersValues.length > 1
370
- ? currentExpression.parametersValues.slice(1)
371
- : [];
372
- expressions.push(propertyExpression);
373
- }
374
- currentExpression = guaranteeNonNullable(
375
- currentExpression.parametersValues[0],
376
- );
377
- }
378
- assertTrue(
379
- expressions.length > 0,
380
- `Can't process exists() expression: exists() usage with non-chain property expression is not supported`,
381
- );
382
- for (let i = 0; i < expressions.length - 1; ++i) {
383
- (
384
- expressions[i] as
385
- | AbstractPropertyExpression
386
- | SimpleFunctionExpression
387
- ).parametersValues.unshift(
388
- expressions[i + 1] as
389
- | AbstractPropertyExpression
390
- | SimpleFunctionExpression,
391
- );
392
- }
393
- (
394
- expressions[expressions.length - 1] as
395
- | AbstractPropertyExpression
396
- | SimpleFunctionExpression
397
- ).parametersValues.unshift(flattenedPropertyExpressionChain);
398
- flattenedPropertyExpressionChain = guaranteeType(
399
- expressions[0],
400
- AbstractPropertyExpression,
401
- `Can't process exists() expression: can't flatten to a property expression`,
402
- );
403
- }
404
-
405
- // 3. Build the filter condition state with the simplified property expression
406
- const filterConditionState = new FilterConditionState(
407
- filterState,
408
- flattenedPropertyExpressionChain,
409
- );
410
- existsLambdaParameterNames.forEach((paramName) =>
411
- filterConditionState.addExistsLambdaParamNames(paramName),
412
- );
413
- return [filterConditionState, mainFilterExpression];
414
- }
415
- return [undefined, undefined];
416
- };
417
-
418
61
  export const buildFilterConditionState = (
419
62
  filterState: QueryBuilderFilterState,
420
63
  expression: SimpleFunctionExpression,
@@ -451,17 +94,6 @@ export const buildFilterConditionState = (
451
94
  )}() expression: expects property expression in lambda body`,
452
95
  );
453
96
 
454
- const variableName =
455
- getPropertyExpressionChainVariable(propertyExpression).name;
456
- assertTrue(
457
- filterState.lambdaParameterName === variableName,
458
- `Can't process ${extractElementNameFromPath(
459
- operatorFunctionFullPath,
460
- )}() expression: expects variable used in lambda body '${variableName}' to match lambda parameter '${
461
- filterState.lambdaParameterName
462
- }'`,
463
- );
464
-
465
97
  filterConditionState = new FilterConditionState(
466
98
  filterState,
467
99
  propertyExpression,
@@ -473,12 +105,40 @@ export const buildFilterConditionState = (
473
105
  QUERY_BUILDER_SUPPORTED_FUNCTIONS.EXISTS,
474
106
  )
475
107
  ) {
476
- [filterConditionState, mainExpressionWithOperator] =
477
- buildFilterConditionStateWithExists(
478
- filterState,
479
- expression,
108
+ const lambdaFunctionInstance = guaranteeType(
109
+ expression.parametersValues[1],
110
+ LambdaFunctionInstanceValue,
111
+ );
112
+ const lambdaFunction = guaranteeType(
113
+ lambdaFunctionInstance.values[0],
114
+ LambdaFunction,
115
+ );
116
+ const filterExpression = guaranteeType(
117
+ lambdaFunction.expressionSequence[0],
118
+ SimpleFunctionExpression,
119
+ );
120
+ assertTrue(
121
+ filterExpression.parametersValues.length === (hasNoValue ? 1 : 2),
122
+ `Can't process ${extractElementNameFromPath(
480
123
  operatorFunctionFullPath,
481
- );
124
+ )}() expression: ${extractElementNameFromPath(
125
+ operatorFunctionFullPath,
126
+ )}() expects ${hasNoValue ? 'no argument' : '1 argument'}`,
127
+ );
128
+
129
+ const propertyExpression = guaranteeType(
130
+ filterExpression.parametersValues[0],
131
+ AbstractPropertyExpression,
132
+ `Can't process ${extractElementNameFromPath(
133
+ operatorFunctionFullPath,
134
+ )}() expression: expects property expression in lambda body`,
135
+ );
136
+
137
+ filterConditionState = new FilterConditionState(
138
+ filterState,
139
+ propertyExpression,
140
+ );
141
+ mainExpressionWithOperator = filterExpression;
482
142
  }
483
143
 
484
144
  // Post-build check: make sure the simple filter condition LHS, RHS, and operator are compatible
@@ -98,10 +98,12 @@ export class QueryBuilderFilterOperator_Contain
98
98
 
99
99
  buildFilterConditionExpression(
100
100
  filterConditionState: FilterConditionState,
101
+ lambdaParameterName?: string | undefined,
101
102
  ): ValueSpecification {
102
103
  return buildFilterConditionExpression(
103
104
  filterConditionState,
104
105
  QUERY_BUILDER_SUPPORTED_FUNCTIONS.CONTAINS,
106
+ lambdaParameterName,
105
107
  );
106
108
  }
107
109
 
@@ -131,9 +133,13 @@ export class QueryBuilderFilterOperator_NotContain extends QueryBuilderFilterOpe
131
133
 
132
134
  override buildFilterConditionExpression(
133
135
  filterConditionState: FilterConditionState,
136
+ lambdaParameterName?: string | undefined,
134
137
  ): ValueSpecification {
135
138
  return buildNotExpression(
136
- super.buildFilterConditionExpression(filterConditionState),
139
+ super.buildFilterConditionExpression(
140
+ filterConditionState,
141
+ lambdaParameterName,
142
+ ),
137
143
  );
138
144
  }
139
145
 
@@ -98,10 +98,12 @@ export class QueryBuilderFilterOperator_EndWith
98
98
 
99
99
  buildFilterConditionExpression(
100
100
  filterConditionState: FilterConditionState,
101
+ lambdaParameterName?: string | undefined,
101
102
  ): ValueSpecification {
102
103
  return buildFilterConditionExpression(
103
104
  filterConditionState,
104
105
  QUERY_BUILDER_SUPPORTED_FUNCTIONS.ENDS_WITH,
106
+ lambdaParameterName,
105
107
  );
106
108
  }
107
109
 
@@ -131,9 +133,13 @@ export class QueryBuilderFilterOperator_NotEndWith extends QueryBuilderFilterOpe
131
133
 
132
134
  override buildFilterConditionExpression(
133
135
  filterConditionState: FilterConditionState,
136
+ lambdaParameterName?: string | undefined,
134
137
  ): ValueSpecification {
135
138
  return buildNotExpression(
136
- super.buildFilterConditionExpression(filterConditionState),
139
+ super.buildFilterConditionExpression(
140
+ filterConditionState,
141
+ lambdaParameterName,
142
+ ),
137
143
  );
138
144
  }
139
145
 
@@ -165,6 +165,7 @@ export class QueryBuilderFilterOperator_Equal
165
165
 
166
166
  buildFilterConditionExpression(
167
167
  filterConditionState: FilterConditionState,
168
+ lambdaParameterName?: string | undefined,
168
169
  ): ValueSpecification {
169
170
  return buildFilterConditionExpression(
170
171
  filterConditionState,
@@ -174,6 +175,7 @@ export class QueryBuilderFilterOperator_Equal
174
175
  PRIMITIVE_TYPE.DATETIME
175
176
  ? QUERY_BUILDER_SUPPORTED_FUNCTIONS.IS_ON_DAY
176
177
  : QUERY_BUILDER_SUPPORTED_FUNCTIONS.EQUAL,
178
+ lambdaParameterName,
177
179
  );
178
180
  }
179
181
 
@@ -208,9 +210,13 @@ export class QueryBuilderFilterOperator_NotEqual extends QueryBuilderFilterOpera
208
210
 
209
211
  override buildFilterConditionExpression(
210
212
  filterConditionState: FilterConditionState,
213
+ lambdaParameterName?: string | undefined,
211
214
  ): ValueSpecification {
212
215
  return buildNotExpression(
213
- super.buildFilterConditionExpression(filterConditionState),
216
+ super.buildFilterConditionExpression(
217
+ filterConditionState,
218
+ lambdaParameterName,
219
+ ),
214
220
  );
215
221
  }
216
222
 
@@ -123,6 +123,7 @@ export class QueryBuilderFilterOperator_GreaterThan
123
123
 
124
124
  buildFilterConditionExpression(
125
125
  filterConditionState: FilterConditionState,
126
+ lambdaParameterName?: string | undefined,
126
127
  ): ValueSpecification {
127
128
  return buildFilterConditionExpression(
128
129
  filterConditionState,
@@ -132,6 +133,7 @@ export class QueryBuilderFilterOperator_GreaterThan
132
133
  PRIMITIVE_TYPE.DATETIME
133
134
  ? QUERY_BUILDER_SUPPORTED_FUNCTIONS.IS_AFTER_DAY
134
135
  : QUERY_BUILDER_SUPPORTED_FUNCTIONS.GREATER_THAN,
136
+ lambdaParameterName,
135
137
  );
136
138
  }
137
139
 
@@ -123,6 +123,7 @@ export class QueryBuilderFilterOperator_GreaterThanEqual
123
123
 
124
124
  buildFilterConditionExpression(
125
125
  filterConditionState: FilterConditionState,
126
+ lambdaParameterName?: string | undefined,
126
127
  ): ValueSpecification {
127
128
  return buildFilterConditionExpression(
128
129
  filterConditionState,
@@ -132,6 +133,7 @@ export class QueryBuilderFilterOperator_GreaterThanEqual
132
133
  PRIMITIVE_TYPE.DATETIME
133
134
  ? QUERY_BUILDER_SUPPORTED_FUNCTIONS.IS_ON_OR_AFTER_DAY
134
135
  : QUERY_BUILDER_SUPPORTED_FUNCTIONS.GREATER_THAN_EQUAL,
136
+ lambdaParameterName,
135
137
  );
136
138
  }
137
139
 
@@ -135,10 +135,12 @@ export class QueryBuilderFilterOperator_In
135
135
 
136
136
  buildFilterConditionExpression(
137
137
  filterConditionState: FilterConditionState,
138
+ lambdaParameterName?: string | undefined,
138
139
  ): ValueSpecification {
139
140
  return buildFilterConditionExpression(
140
141
  filterConditionState,
141
142
  QUERY_BUILDER_SUPPORTED_FUNCTIONS.IN,
143
+ lambdaParameterName,
142
144
  );
143
145
  }
144
146
 
@@ -166,9 +168,13 @@ export class QueryBuilderFilterOperator_NotIn extends QueryBuilderFilterOperator
166
168
 
167
169
  override buildFilterConditionExpression(
168
170
  filterConditionState: FilterConditionState,
171
+ lambdaParameterName?: string | undefined,
169
172
  ): ValueSpecification {
170
173
  return buildNotExpression(
171
- super.buildFilterConditionExpression(filterConditionState),
174
+ super.buildFilterConditionExpression(
175
+ filterConditionState,
176
+ lambdaParameterName,
177
+ ),
172
178
  );
173
179
  }
174
180
 
@@ -80,10 +80,12 @@ export class QueryBuilderFilterOperator_IsEmpty
80
80
 
81
81
  buildFilterConditionExpression(
82
82
  filterConditionState: FilterConditionState,
83
+ lambdaParameterName?: string | undefined,
83
84
  ): ValueSpecification {
84
85
  return buildFilterConditionExpression(
85
86
  filterConditionState,
86
87
  QUERY_BUILDER_SUPPORTED_FUNCTIONS.IS_EMPTY,
88
+ lambdaParameterName,
87
89
  );
88
90
  }
89
91
 
@@ -114,9 +116,13 @@ export class QueryBuilderFilterOperator_IsNotEmpty extends QueryBuilderFilterOpe
114
116
 
115
117
  override buildFilterConditionExpression(
116
118
  filterConditionState: FilterConditionState,
119
+ lambdaParameterName?: string | undefined,
117
120
  ): ValueSpecification {
118
121
  return buildNotExpression(
119
- super.buildFilterConditionExpression(filterConditionState),
122
+ super.buildFilterConditionExpression(
123
+ filterConditionState,
124
+ lambdaParameterName,
125
+ ),
120
126
  );
121
127
  }
122
128
 
@@ -123,6 +123,7 @@ export class QueryBuilderFilterOperator_LessThan
123
123
 
124
124
  buildFilterConditionExpression(
125
125
  filterConditionState: FilterConditionState,
126
+ lambdaParameterName?: string | undefined,
126
127
  ): ValueSpecification {
127
128
  return buildFilterConditionExpression(
128
129
  filterConditionState,
@@ -132,6 +133,7 @@ export class QueryBuilderFilterOperator_LessThan
132
133
  PRIMITIVE_TYPE.DATETIME
133
134
  ? QUERY_BUILDER_SUPPORTED_FUNCTIONS.IS_BEFORE_DAY
134
135
  : QUERY_BUILDER_SUPPORTED_FUNCTIONS.LESS_THAN,
136
+ lambdaParameterName,
135
137
  );
136
138
  }
137
139
 
@@ -123,6 +123,7 @@ export class QueryBuilderFilterOperator_LessThanEqual
123
123
 
124
124
  buildFilterConditionExpression(
125
125
  filterConditionState: FilterConditionState,
126
+ lambdaParameterName?: string | undefined,
126
127
  ): ValueSpecification {
127
128
  return buildFilterConditionExpression(
128
129
  filterConditionState,
@@ -132,6 +133,7 @@ export class QueryBuilderFilterOperator_LessThanEqual
132
133
  PRIMITIVE_TYPE.DATETIME
133
134
  ? QUERY_BUILDER_SUPPORTED_FUNCTIONS.IS_ON_OR_BEFORE_DAY
134
135
  : QUERY_BUILDER_SUPPORTED_FUNCTIONS.LESS_THAN_EQUAL,
136
+ lambdaParameterName,
135
137
  );
136
138
  }
137
139