@finos/legend-query-builder 4.1.15 → 4.2.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 (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