@finos/legend-query-builder 4.18.1 → 4.18.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/QueryBuilder.d.ts.map +1 -1
- package/lib/components/QueryBuilder.js +0 -1
- package/lib/components/QueryBuilder.js.map +1 -1
- package/lib/components/QueryBuilderSideBar.d.ts.map +1 -1
- package/lib/components/QueryBuilderSideBar.js +10 -2
- package/lib/components/QueryBuilderSideBar.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +5 -3
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
- package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
- package/lib/components/filter/QueryBuilderFilterPanel.js +74 -36
- package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
- package/lib/components/result/tds/QueryBuilderTDSCellSelectionStatsBar.d.ts.map +1 -1
- package/lib/components/result/tds/QueryBuilderTDSCellSelectionStatsBar.js +15 -3
- package/lib/components/result/tds/QueryBuilderTDSCellSelectionStatsBar.js.map +1 -1
- package/lib/components/result/tds/QueryBuilderTDSResultShared.d.ts.map +1 -1
- package/lib/components/result/tds/QueryBuilderTDSResultShared.js +5 -3
- package/lib/components/result/tds/QueryBuilderTDSResultShared.js.map +1 -1
- package/lib/components/sql-playground/SQLPlaygroundPanel.d.ts.map +1 -1
- package/lib/components/sql-playground/SQLPlaygroundPanel.js +9 -5
- package/lib/components/sql-playground/SQLPlaygroundPanel.js.map +1 -1
- package/lib/data-access-overview.css +1 -1
- package/lib/index.css +1 -17
- package/lib/index.css.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/QueryBuilderStateBuilder.d.ts +1 -1
- package/lib/stores/QueryBuilderStateBuilder.d.ts.map +1 -1
- package/lib/stores/QueryBuilderStateBuilder.js +10 -2
- package/lib/stores/QueryBuilderStateBuilder.js.map +1 -1
- package/lib/stores/QueryBuilderStateHashUtils.d.ts +2 -0
- package/lib/stores/QueryBuilderStateHashUtils.d.ts.map +1 -1
- package/lib/stores/QueryBuilderStateHashUtils.js +2 -0
- package/lib/stores/QueryBuilderStateHashUtils.js.map +1 -1
- package/lib/stores/__test-utils__/TEST_DATA__QueryBuilder_Accessors.d.ts +98 -0
- package/lib/stores/__test-utils__/TEST_DATA__QueryBuilder_Accessors.d.ts.map +1 -1
- package/lib/stores/__test-utils__/TEST_DATA__QueryBuilder_Accessors.js +156 -0
- package/lib/stores/__test-utils__/TEST_DATA__QueryBuilder_Accessors.js.map +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.d.ts +50 -4
- package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.js +112 -11
- package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
- package/lib/stores/filter/QueryBuilderFilterStateBuilder.d.ts.map +1 -1
- package/lib/stores/filter/QueryBuilderFilterStateBuilder.js +17 -3
- package/lib/stores/filter/QueryBuilderFilterStateBuilder.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.d.ts +6 -0
- package/lib/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.js +35 -9
- package/lib/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.js +2 -4
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.js +2 -4
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.js +7 -11
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.js +7 -11
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.js +7 -11
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.js +3 -6
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.d.ts +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.js +5 -3
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.js +7 -11
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.js +7 -11
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.js +2 -4
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.js.map +1 -1
- package/lib/stores/milestoning/QueryBuilderMilestoningState.d.ts.map +1 -1
- package/lib/stores/milestoning/QueryBuilderMilestoningState.js +9 -6
- package/lib/stores/milestoning/QueryBuilderMilestoningState.js.map +1 -1
- package/lib/stores/workflows/accessor/AccessorQueryBuilderState.d.ts +1 -2
- package/lib/stores/workflows/accessor/AccessorQueryBuilderState.d.ts.map +1 -1
- package/lib/stores/workflows/accessor/AccessorQueryBuilderState.js +1 -3
- package/lib/stores/workflows/accessor/AccessorQueryBuilderState.js.map +1 -1
- package/lib/stores/workflows/dataProduct/DataProductQueryBuilderState.d.ts +11 -6
- package/lib/stores/workflows/dataProduct/DataProductQueryBuilderState.d.ts.map +1 -1
- package/lib/stores/workflows/dataProduct/DataProductQueryBuilderState.js +150 -49
- package/lib/stores/workflows/dataProduct/DataProductQueryBuilderState.js.map +1 -1
- package/package.json +10 -10
- package/src/components/QueryBuilder.tsx +0 -1
- package/src/components/QueryBuilderSideBar.tsx +10 -7
- package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +7 -2
- package/src/components/filter/QueryBuilderFilterPanel.tsx +138 -69
- package/src/components/result/tds/QueryBuilderTDSCellSelectionStatsBar.tsx +33 -3
- package/src/components/result/tds/QueryBuilderTDSResultShared.tsx +4 -1
- package/src/components/sql-playground/SQLPlaygroundPanel.tsx +10 -5
- package/src/index.ts +1 -1
- package/src/stores/QueryBuilderStateBuilder.ts +15 -2
- package/src/stores/QueryBuilderStateHashUtils.ts +2 -0
- package/src/stores/__test-utils__/TEST_DATA__QueryBuilder_Accessors.ts +157 -0
- package/src/stores/filter/QueryBuilderFilterState.ts +175 -14
- package/src/stores/filter/QueryBuilderFilterStateBuilder.ts +24 -3
- package/src/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.ts +55 -24
- package/src/stores/filter/operators/QueryBuilderFilterOperator_Contain.ts +2 -5
- package/src/stores/filter/operators/QueryBuilderFilterOperator_EndWith.ts +2 -5
- package/src/stores/filter/operators/QueryBuilderFilterOperator_Equal.ts +7 -13
- package/src/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.ts +7 -13
- package/src/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.ts +7 -13
- package/src/stores/filter/operators/QueryBuilderFilterOperator_In.ts +3 -9
- package/src/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.ts +9 -6
- package/src/stores/filter/operators/QueryBuilderFilterOperator_LessThan.ts +7 -13
- package/src/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.ts +7 -13
- package/src/stores/filter/operators/QueryBuilderFilterOperator_StartWith.ts +2 -5
- package/src/stores/milestoning/QueryBuilderMilestoningState.ts +13 -7
- package/src/stores/workflows/accessor/AccessorQueryBuilderState.ts +1 -3
- package/src/stores/workflows/dataProduct/DataProductQueryBuilderState.ts +245 -76
|
@@ -14,6 +14,163 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
export const TEST_DATA__QueryBuilder_Accessors_SimpleProjection_WithFilter = {
|
|
18
|
+
_type: 'lambda',
|
|
19
|
+
body: [
|
|
20
|
+
{
|
|
21
|
+
_type: 'func',
|
|
22
|
+
function: 'from',
|
|
23
|
+
parameters: [
|
|
24
|
+
{
|
|
25
|
+
_type: 'func',
|
|
26
|
+
function: 'project',
|
|
27
|
+
parameters: [
|
|
28
|
+
{
|
|
29
|
+
_type: 'func',
|
|
30
|
+
function: 'filter',
|
|
31
|
+
parameters: [
|
|
32
|
+
{
|
|
33
|
+
_type: 'classInstance',
|
|
34
|
+
multiplicity: {
|
|
35
|
+
lowerBound: 1,
|
|
36
|
+
upperBound: 1,
|
|
37
|
+
},
|
|
38
|
+
type: '>',
|
|
39
|
+
value: {
|
|
40
|
+
path: ['database::TestDatabase', 'default', 'TEST0'],
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
_type: 'lambda',
|
|
45
|
+
body: [
|
|
46
|
+
{
|
|
47
|
+
_type: 'func',
|
|
48
|
+
function: 'and',
|
|
49
|
+
parameters: [
|
|
50
|
+
{
|
|
51
|
+
_type: 'func',
|
|
52
|
+
function: 'equal',
|
|
53
|
+
parameters: [
|
|
54
|
+
{
|
|
55
|
+
_type: 'property',
|
|
56
|
+
parameters: [
|
|
57
|
+
{
|
|
58
|
+
_type: 'var',
|
|
59
|
+
name: 'x',
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
property: 'FIRSTNAME',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
_type: 'string',
|
|
66
|
+
value: 'John',
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
_type: 'func',
|
|
72
|
+
function: 'equal',
|
|
73
|
+
parameters: [
|
|
74
|
+
{
|
|
75
|
+
_type: 'property',
|
|
76
|
+
parameters: [
|
|
77
|
+
{
|
|
78
|
+
_type: 'var',
|
|
79
|
+
name: 'x',
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
property: 'LASTNAME',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
_type: 'string',
|
|
86
|
+
value: 'Doe',
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
parameters: [
|
|
94
|
+
{
|
|
95
|
+
_type: 'var',
|
|
96
|
+
name: 'x',
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
_type: 'classInstance',
|
|
104
|
+
multiplicity: {
|
|
105
|
+
lowerBound: 1,
|
|
106
|
+
upperBound: 1,
|
|
107
|
+
},
|
|
108
|
+
type: 'colSpecArray',
|
|
109
|
+
value: {
|
|
110
|
+
colSpecs: [
|
|
111
|
+
{
|
|
112
|
+
function1: {
|
|
113
|
+
_type: 'lambda',
|
|
114
|
+
body: [
|
|
115
|
+
{
|
|
116
|
+
_type: 'property',
|
|
117
|
+
parameters: [
|
|
118
|
+
{
|
|
119
|
+
_type: 'var',
|
|
120
|
+
name: 'x',
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
property: 'FIRSTNAME',
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
parameters: [
|
|
127
|
+
{
|
|
128
|
+
_type: 'var',
|
|
129
|
+
name: 'x',
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
name: 'Firstname',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
function1: {
|
|
137
|
+
_type: 'lambda',
|
|
138
|
+
body: [
|
|
139
|
+
{
|
|
140
|
+
_type: 'property',
|
|
141
|
+
parameters: [
|
|
142
|
+
{
|
|
143
|
+
_type: 'var',
|
|
144
|
+
name: 'x',
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
property: 'LASTNAME',
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
parameters: [
|
|
151
|
+
{
|
|
152
|
+
_type: 'var',
|
|
153
|
+
name: 'x',
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
name: 'Lastname',
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
_type: 'packageableElementPtr',
|
|
166
|
+
fullPath: 'runtime::TestRuntime',
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
parameters: [],
|
|
172
|
+
};
|
|
173
|
+
|
|
17
174
|
export const TEST_DATA__QueryBuilder_Accessors_SimpleProjection_WithPostFilter =
|
|
18
175
|
{
|
|
19
176
|
_type: 'lambda',
|
|
@@ -32,7 +32,10 @@ import {
|
|
|
32
32
|
hashArray,
|
|
33
33
|
isNonNullable,
|
|
34
34
|
} from '@finos/legend-shared';
|
|
35
|
-
import type {
|
|
35
|
+
import type {
|
|
36
|
+
QueryBuilderExplorerTreeDragSource,
|
|
37
|
+
QueryBuilderExplorerTreeRelationColumnDragSource,
|
|
38
|
+
} from '../explorer/QueryBuilderExplorerState.js';
|
|
36
39
|
import { QueryBuilderPropertyExpressionState } from '../QueryBuilderPropertyEditorState.js';
|
|
37
40
|
import type { QueryBuilderState } from '../QueryBuilderState.js';
|
|
38
41
|
import {
|
|
@@ -46,6 +49,9 @@ import {
|
|
|
46
49
|
InstanceValue,
|
|
47
50
|
SimpleFunctionExpression,
|
|
48
51
|
matchFunctionName,
|
|
52
|
+
FunctionExpression,
|
|
53
|
+
Multiplicity,
|
|
54
|
+
VariableExpression as VariableExpressionClass,
|
|
49
55
|
} from '@finos/legend-graph';
|
|
50
56
|
import { DEFAULT_LAMBDA_VARIABLE_NAME } from '../QueryBuilderConfig.js';
|
|
51
57
|
import type { QueryBuilderProjectionColumnDragSource } from '../fetch-structure/tds/projection/QueryBuilderProjectionColumnState.js';
|
|
@@ -66,6 +72,7 @@ import {
|
|
|
66
72
|
import { instanceValue_setValues } from '../shared/ValueSpecificationModifierHelper.js';
|
|
67
73
|
import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '../../graph/QueryBuilderMetaModelConst.js';
|
|
68
74
|
import type { QueryBuilderVariableDragSource } from '../../components/shared/BasicValueSpecificationEditor.js';
|
|
75
|
+
import { buildPropertyExpressionChain } from '../QueryBuilderValueSpecificationBuilderHelper.js';
|
|
69
76
|
|
|
70
77
|
export enum QUERY_BUILDER_FILTER_DND_TYPE {
|
|
71
78
|
GROUP_CONDITION = 'QUERY_BUILDER_FILTER_DND_TYPE.GROUP_CONDITION',
|
|
@@ -79,6 +86,7 @@ export interface QueryBuilderFilterConditionDragSource {
|
|
|
79
86
|
|
|
80
87
|
export type QueryBuilderFilterNodeDropTarget =
|
|
81
88
|
| QueryBuilderExplorerTreeDragSource
|
|
89
|
+
| QueryBuilderExplorerTreeRelationColumnDragSource
|
|
82
90
|
| QueryBuilderProjectionColumnDragSource
|
|
83
91
|
| QueryBuilderFilterConditionDragSource;
|
|
84
92
|
|
|
@@ -229,9 +237,137 @@ export class FilterPropertyExpressionStateConditionValueState extends FilterCond
|
|
|
229
237
|
}
|
|
230
238
|
}
|
|
231
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Abstract base class for the left-hand side (source) of a filter condition.
|
|
242
|
+
* This allows filtering on different source types (class properties, relation columns)
|
|
243
|
+
* without operators needing to know the specifics of the source.
|
|
244
|
+
*/
|
|
245
|
+
export abstract class FilterConditionSourceState implements Hashable {
|
|
246
|
+
abstract get type(): Type;
|
|
247
|
+
abstract get label(): string;
|
|
248
|
+
abstract get title(): string;
|
|
249
|
+
abstract get isValid(): boolean;
|
|
250
|
+
abstract get requiresExistsHandling(): boolean;
|
|
251
|
+
abstract buildLeftExpression(
|
|
252
|
+
queryBuilderState: QueryBuilderState,
|
|
253
|
+
lambdaParameterName: string,
|
|
254
|
+
): ValueSpecification;
|
|
255
|
+
abstract get hashCode(): string;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export class FilterPropertyExpressionSourceState extends FilterConditionSourceState {
|
|
259
|
+
readonly propertyExpressionState: QueryBuilderPropertyExpressionState;
|
|
260
|
+
|
|
261
|
+
constructor(propertyExpressionState: QueryBuilderPropertyExpressionState) {
|
|
262
|
+
super();
|
|
263
|
+
this.propertyExpressionState = propertyExpressionState;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
get type(): Type {
|
|
267
|
+
return this.propertyExpressionState.propertyExpression.func.value
|
|
268
|
+
.genericType.value.rawType;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
get label(): string {
|
|
272
|
+
return this.propertyExpressionState.title;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
get title(): string {
|
|
276
|
+
return this.propertyExpressionState.title;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
get isValid(): boolean {
|
|
280
|
+
return this.propertyExpressionState.isValid;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
get requiresExistsHandling(): boolean {
|
|
284
|
+
return this.propertyExpressionState.requiresExistsHandling;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
buildLeftExpression(
|
|
288
|
+
queryBuilderState: QueryBuilderState,
|
|
289
|
+
lambdaParameterName: string,
|
|
290
|
+
): ValueSpecification {
|
|
291
|
+
return guaranteeNonNullable(
|
|
292
|
+
buildPropertyExpressionChain(
|
|
293
|
+
this.propertyExpressionState.propertyExpression,
|
|
294
|
+
queryBuilderState,
|
|
295
|
+
lambdaParameterName,
|
|
296
|
+
),
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
get hashCode(): string {
|
|
301
|
+
return hashArray([
|
|
302
|
+
QUERY_BUILDER_STATE_HASH_STRUCTURE.FILTER_CONDITION_SOURCE_PROPERTY_EXPRESSION,
|
|
303
|
+
this.propertyExpressionState,
|
|
304
|
+
]);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export class FilterRelationColumnSourceState extends FilterConditionSourceState {
|
|
309
|
+
readonly columnName: string;
|
|
310
|
+
readonly columnType: Type;
|
|
311
|
+
|
|
312
|
+
constructor(columnName: string, columnType: Type) {
|
|
313
|
+
super();
|
|
314
|
+
this.columnName = columnName;
|
|
315
|
+
this.columnType = columnType;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
get type(): Type {
|
|
319
|
+
return this.columnType;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
get label(): string {
|
|
323
|
+
return this.columnName;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
get title(): string {
|
|
327
|
+
return this.columnName;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
get isValid(): boolean {
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
get requiresExistsHandling(): boolean {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
buildLeftExpression(
|
|
339
|
+
queryBuilderState: QueryBuilderState,
|
|
340
|
+
lambdaParameterName: string,
|
|
341
|
+
): ValueSpecification {
|
|
342
|
+
const relationType = queryBuilderState.sourceRelationType;
|
|
343
|
+
if (relationType) {
|
|
344
|
+
const col = guaranteeNonNullable(
|
|
345
|
+
relationType.columns.find((c) => c.name === this.columnName),
|
|
346
|
+
`Can't find column '${this.columnName}' in relation`,
|
|
347
|
+
);
|
|
348
|
+
const funcExp = new FunctionExpression(col.name);
|
|
349
|
+
funcExp.func = col;
|
|
350
|
+
funcExp.parametersValues = [
|
|
351
|
+
new VariableExpressionClass(lambdaParameterName, Multiplicity.ONE),
|
|
352
|
+
];
|
|
353
|
+
return funcExp;
|
|
354
|
+
}
|
|
355
|
+
throw new IllegalStateError(
|
|
356
|
+
`Can't build expression for relation column '${this.columnName}': no source relation type`,
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
get hashCode(): string {
|
|
361
|
+
return hashArray([
|
|
362
|
+
QUERY_BUILDER_STATE_HASH_STRUCTURE.FILTER_CONDITION_SOURCE_RELATION_COLUMN,
|
|
363
|
+
this.columnName,
|
|
364
|
+
]);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
232
368
|
export class FilterConditionState implements Hashable {
|
|
233
369
|
readonly filterState: QueryBuilderFilterState;
|
|
234
|
-
|
|
370
|
+
sourceState: FilterConditionSourceState;
|
|
235
371
|
operator!: QueryBuilderFilterOperator;
|
|
236
372
|
rightConditionValue?: FilterConditionValueState | undefined;
|
|
237
373
|
existsLambdaParamNames: string[] = [];
|
|
@@ -240,11 +376,11 @@ export class FilterConditionState implements Hashable {
|
|
|
240
376
|
|
|
241
377
|
constructor(
|
|
242
378
|
filterState: QueryBuilderFilterState,
|
|
243
|
-
|
|
379
|
+
source: AbstractPropertyExpression | FilterConditionSourceState,
|
|
244
380
|
operator?: QueryBuilderFilterOperator,
|
|
245
381
|
) {
|
|
246
382
|
makeObservable(this, {
|
|
247
|
-
|
|
383
|
+
sourceState: observable,
|
|
248
384
|
operator: observable,
|
|
249
385
|
rightConditionValue: observable,
|
|
250
386
|
existsLambdaParamNames: observable,
|
|
@@ -261,10 +397,16 @@ export class FilterConditionState implements Hashable {
|
|
|
261
397
|
});
|
|
262
398
|
|
|
263
399
|
this.filterState = filterState;
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
400
|
+
if (source instanceof AbstractPropertyExpression) {
|
|
401
|
+
this.sourceState = new FilterPropertyExpressionSourceState(
|
|
402
|
+
new QueryBuilderPropertyExpressionState(
|
|
403
|
+
filterState.queryBuilderState,
|
|
404
|
+
source,
|
|
405
|
+
),
|
|
406
|
+
);
|
|
407
|
+
} else {
|
|
408
|
+
this.sourceState = source;
|
|
409
|
+
}
|
|
268
410
|
|
|
269
411
|
// operator
|
|
270
412
|
if (operator) {
|
|
@@ -272,7 +414,7 @@ export class FilterConditionState implements Hashable {
|
|
|
272
414
|
} else {
|
|
273
415
|
assertTrue(
|
|
274
416
|
this.operators.length !== 0,
|
|
275
|
-
`Can't find an operator for property '${this.
|
|
417
|
+
`Can't find an operator for property '${this.sourceState.title}': no operators registered`,
|
|
276
418
|
);
|
|
277
419
|
this.operator = this.operators[0] as QueryBuilderFilterOperator;
|
|
278
420
|
}
|
|
@@ -281,6 +423,25 @@ export class FilterConditionState implements Hashable {
|
|
|
281
423
|
);
|
|
282
424
|
}
|
|
283
425
|
|
|
426
|
+
/**
|
|
427
|
+
* Backward-compatible accessor for the property expression state.
|
|
428
|
+
* Only valid when the source is a property expression.
|
|
429
|
+
*/
|
|
430
|
+
get propertyExpressionState(): QueryBuilderPropertyExpressionState {
|
|
431
|
+
return guaranteeType(
|
|
432
|
+
this.sourceState,
|
|
433
|
+
FilterPropertyExpressionSourceState,
|
|
434
|
+
`Filter condition source is not a property expression`,
|
|
435
|
+
).propertyExpressionState;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* The raw type of the left-hand side of the filter condition.
|
|
440
|
+
*/
|
|
441
|
+
get leftConditionType(): Type {
|
|
442
|
+
return this.sourceState.type;
|
|
443
|
+
}
|
|
444
|
+
|
|
284
445
|
get operators(): QueryBuilderFilterOperator[] {
|
|
285
446
|
return this.filterState.operators.filter((op) =>
|
|
286
447
|
op.isCompatibleWithFilterConditionProperty(this),
|
|
@@ -412,7 +573,7 @@ export class FilterConditionState implements Hashable {
|
|
|
412
573
|
get hashCode(): string {
|
|
413
574
|
return hashArray([
|
|
414
575
|
QUERY_BUILDER_STATE_HASH_STRUCTURE.FILTER_CONDITION_STATE,
|
|
415
|
-
this.
|
|
576
|
+
this.sourceState,
|
|
416
577
|
this.rightConditionValue ?? '',
|
|
417
578
|
this.operator,
|
|
418
579
|
]);
|
|
@@ -636,7 +797,7 @@ export class QueryBuilderFilterTreeConditionNodeData
|
|
|
636
797
|
}
|
|
637
798
|
|
|
638
799
|
get dragPreviewLabel(): string {
|
|
639
|
-
return this.condition.
|
|
800
|
+
return this.condition.sourceState.title;
|
|
640
801
|
}
|
|
641
802
|
|
|
642
803
|
get hashCode(): string {
|
|
@@ -1181,7 +1342,7 @@ export class QueryBuilderFilterState
|
|
|
1181
1342
|
): boolean {
|
|
1182
1343
|
return (
|
|
1183
1344
|
node instanceof QueryBuilderFilterTreeConditionNodeData &&
|
|
1184
|
-
!node.condition.
|
|
1345
|
+
!node.condition.sourceState.isValid
|
|
1185
1346
|
);
|
|
1186
1347
|
}
|
|
1187
1348
|
|
|
@@ -1212,12 +1373,12 @@ export class QueryBuilderFilterState
|
|
|
1212
1373
|
if (node instanceof QueryBuilderFilterTreeConditionNodeData) {
|
|
1213
1374
|
if (this.isInvalidValueSpecFilterValue(node)) {
|
|
1214
1375
|
validationIssues.push(
|
|
1215
|
-
`Filter value for ${node.condition.
|
|
1376
|
+
`Filter value for ${node.condition.sourceState.title} is missing or invalid`,
|
|
1216
1377
|
);
|
|
1217
1378
|
}
|
|
1218
1379
|
if (this.isInvalidFilterPropertyExpressionState(node)) {
|
|
1219
1380
|
validationIssues.push(
|
|
1220
|
-
`Derived property parameter value for ${node.condition.
|
|
1381
|
+
`Derived property parameter value for ${node.condition.sourceState.title} is missing or invalid`,
|
|
1221
1382
|
);
|
|
1222
1383
|
}
|
|
1223
1384
|
if (
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
SimpleFunctionExpression,
|
|
24
24
|
type ValueSpecification,
|
|
25
25
|
VariableExpression,
|
|
26
|
+
FunctionExpression,
|
|
26
27
|
} from '@finos/legend-graph';
|
|
27
28
|
import {
|
|
28
29
|
assertTrue,
|
|
@@ -42,6 +43,7 @@ import {
|
|
|
42
43
|
QueryBuilderFilterTreeGroupNodeData,
|
|
43
44
|
QueryBuilderFilterTreeExistsNodeData,
|
|
44
45
|
QueryBuilderFilterTreeOperationNodeData,
|
|
46
|
+
FilterRelationColumnSourceState,
|
|
45
47
|
} from './QueryBuilderFilterState.js';
|
|
46
48
|
|
|
47
49
|
const getPropertyExpressionChainVariable = (
|
|
@@ -321,9 +323,28 @@ const processFilterTree = (
|
|
|
321
323
|
operator.buildFilterConditionState(filterState, expression),
|
|
322
324
|
);
|
|
323
325
|
if (filterConditionState) {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
326
|
+
// Extract the variable name from the filter condition's left side.
|
|
327
|
+
// For relation column sources, the variable comes from the FunctionExpression's parameter;
|
|
328
|
+
// for property expression sources, it comes from the property expression chain.
|
|
329
|
+
let variableName: string;
|
|
330
|
+
if (
|
|
331
|
+
filterConditionState.sourceState instanceof
|
|
332
|
+
FilterRelationColumnSourceState
|
|
333
|
+
) {
|
|
334
|
+
const leftSide = expression.parametersValues[0];
|
|
335
|
+
const varExpr = guaranteeType(
|
|
336
|
+
leftSide instanceof FunctionExpression
|
|
337
|
+
? leftSide.parametersValues[0]
|
|
338
|
+
: undefined,
|
|
339
|
+
VariableExpression,
|
|
340
|
+
`Can't process filter expression: relation column filter must reference a variable`,
|
|
341
|
+
);
|
|
342
|
+
variableName = varExpr.name;
|
|
343
|
+
} else {
|
|
344
|
+
variableName = getPropertyExpressionChainVariable(
|
|
345
|
+
filterConditionState.propertyExpressionState.propertyExpression,
|
|
346
|
+
).name;
|
|
347
|
+
}
|
|
327
348
|
const parentLambdaVariableName =
|
|
328
349
|
parentNode instanceof QueryBuilderFilterTreeOperationNodeData &&
|
|
329
350
|
parentNode.lambdaParameterName
|
|
@@ -22,15 +22,14 @@ import {
|
|
|
22
22
|
AbstractPropertyExpression,
|
|
23
23
|
SimpleFunctionExpression,
|
|
24
24
|
LambdaFunction,
|
|
25
|
+
FunctionExpression,
|
|
26
|
+
RelationColumn,
|
|
25
27
|
} from '@finos/legend-graph';
|
|
26
|
-
import {
|
|
27
|
-
guaranteeType,
|
|
28
|
-
guaranteeNonNullable,
|
|
29
|
-
assertTrue,
|
|
30
|
-
} from '@finos/legend-shared';
|
|
28
|
+
import { guaranteeType, assertTrue } from '@finos/legend-shared';
|
|
31
29
|
import {
|
|
32
30
|
FilterConditionState,
|
|
33
31
|
FilterPropertyExpressionStateConditionValueState,
|
|
32
|
+
FilterRelationColumnSourceState,
|
|
34
33
|
FilterValueSpecConditionValueState,
|
|
35
34
|
type QueryBuilderFilterState,
|
|
36
35
|
} from '../QueryBuilderFilterState.js';
|
|
@@ -48,12 +47,13 @@ export const buildFilterConditionExpression = (
|
|
|
48
47
|
const expression = new SimpleFunctionExpression(
|
|
49
48
|
extractElementNameFromPath(operatorFunctionFullPath),
|
|
50
49
|
);
|
|
51
|
-
const
|
|
52
|
-
filterConditionState.
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
const resolvedLambdaParameterName =
|
|
51
|
+
lambdaParameterName ?? filterConditionState.filterState.lambdaParameterName;
|
|
52
|
+
const leftExpression = filterConditionState.sourceState.buildLeftExpression(
|
|
53
|
+
filterConditionState.filterState.queryBuilderState,
|
|
54
|
+
resolvedLambdaParameterName,
|
|
55
55
|
);
|
|
56
|
-
expression.parametersValues.push(
|
|
56
|
+
expression.parametersValues.push(leftExpression);
|
|
57
57
|
// NOTE: there are simple operators which do not require any params (e.g. isEmpty)
|
|
58
58
|
if (
|
|
59
59
|
filterConditionState.rightConditionValue &&
|
|
@@ -72,15 +72,35 @@ export const buildFilterConditionExpression = (
|
|
|
72
72
|
const rightConditionPropertyExpression = buildPropertyExpressionChain(
|
|
73
73
|
filterConditionState.rightConditionValue.propertyExpressionState
|
|
74
74
|
.propertyExpression,
|
|
75
|
-
filterConditionState.
|
|
76
|
-
|
|
77
|
-
filterConditionState.filterState.lambdaParameterName,
|
|
75
|
+
filterConditionState.filterState.queryBuilderState,
|
|
76
|
+
resolvedLambdaParameterName,
|
|
78
77
|
);
|
|
79
78
|
expression.parametersValues.push(rightConditionPropertyExpression);
|
|
80
79
|
}
|
|
81
80
|
return expression;
|
|
82
81
|
};
|
|
83
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Extracts the raw type path from the left-hand side of a filter expression.
|
|
85
|
+
* Handles both AbstractPropertyExpression (class properties) and
|
|
86
|
+
* FunctionExpression with RelationColumn (relation column properties).
|
|
87
|
+
*/
|
|
88
|
+
export const getFilterExpressionLeftSideTypePath = (
|
|
89
|
+
expression: SimpleFunctionExpression,
|
|
90
|
+
): string | undefined => {
|
|
91
|
+
const leftSide = expression.parametersValues[0];
|
|
92
|
+
if (leftSide instanceof AbstractPropertyExpression) {
|
|
93
|
+
return leftSide.func.value.genericType.value.rawType.path;
|
|
94
|
+
}
|
|
95
|
+
if (
|
|
96
|
+
leftSide instanceof FunctionExpression &&
|
|
97
|
+
leftSide.func instanceof RelationColumn
|
|
98
|
+
) {
|
|
99
|
+
return leftSide.func.genericType.value.rawType.path;
|
|
100
|
+
}
|
|
101
|
+
return undefined;
|
|
102
|
+
};
|
|
103
|
+
|
|
84
104
|
export const buildFilterConditionState = (
|
|
85
105
|
filterState: QueryBuilderFilterState,
|
|
86
106
|
expression: SimpleFunctionExpression,
|
|
@@ -109,18 +129,29 @@ export const buildFilterConditionState = (
|
|
|
109
129
|
)}() expects ${hasNoValue ? 'no argument' : '1 argument'}`,
|
|
110
130
|
);
|
|
111
131
|
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
)
|
|
132
|
+
const leftSide = expression.parametersValues[0];
|
|
133
|
+
if (leftSide instanceof AbstractPropertyExpression) {
|
|
134
|
+
filterConditionState = new FilterConditionState(filterState, leftSide);
|
|
135
|
+
} else if (
|
|
136
|
+
leftSide instanceof FunctionExpression &&
|
|
137
|
+
leftSide.func instanceof RelationColumn
|
|
138
|
+
) {
|
|
139
|
+
const col = leftSide.func;
|
|
140
|
+
filterConditionState = new FilterConditionState(
|
|
141
|
+
filterState,
|
|
142
|
+
new FilterRelationColumnSourceState(
|
|
143
|
+
col.name,
|
|
144
|
+
col.genericType.value.rawType,
|
|
145
|
+
),
|
|
146
|
+
);
|
|
147
|
+
} else {
|
|
148
|
+
throw new Error(
|
|
149
|
+
`Can't process ${extractElementNameFromPath(
|
|
150
|
+
operatorFunctionFullPath,
|
|
151
|
+
)}() expression: expects property expression or relation column in lambda body`,
|
|
152
|
+
);
|
|
153
|
+
}
|
|
119
154
|
|
|
120
|
-
filterConditionState = new FilterConditionState(
|
|
121
|
-
filterState,
|
|
122
|
-
propertyExpression,
|
|
123
|
-
);
|
|
124
155
|
mainExpressionWithOperator = expression;
|
|
125
156
|
} else if (
|
|
126
157
|
matchFunctionName(
|
|
@@ -55,8 +55,7 @@ export class QueryBuilderFilterOperator_Contain
|
|
|
55
55
|
): boolean {
|
|
56
56
|
return (
|
|
57
57
|
getStandardPrimitiveTypeEquivalent(
|
|
58
|
-
filterConditionState.
|
|
59
|
-
.value.genericType.value.rawType,
|
|
58
|
+
filterConditionState.leftConditionType,
|
|
60
59
|
) === PRIMITIVE_TYPE.STRING
|
|
61
60
|
);
|
|
62
61
|
}
|
|
@@ -78,9 +77,7 @@ export class QueryBuilderFilterOperator_Contain
|
|
|
78
77
|
getDefaultFilterConditionValue(
|
|
79
78
|
filterConditionState: FilterConditionState,
|
|
80
79
|
): ValueSpecification | undefined {
|
|
81
|
-
const propertyType =
|
|
82
|
-
filterConditionState.propertyExpressionState.propertyExpression.func.value
|
|
83
|
-
.genericType.value.rawType;
|
|
80
|
+
const propertyType = filterConditionState.leftConditionType;
|
|
84
81
|
switch (propertyType.path) {
|
|
85
82
|
case PRIMITIVE_TYPE.STRING: {
|
|
86
83
|
return buildDefaultInstanceValue(
|
|
@@ -55,8 +55,7 @@ export class QueryBuilderFilterOperator_EndWith
|
|
|
55
55
|
): boolean {
|
|
56
56
|
return (
|
|
57
57
|
getStandardPrimitiveTypeEquivalent(
|
|
58
|
-
filterConditionState.
|
|
59
|
-
.value.genericType.value.rawType,
|
|
58
|
+
filterConditionState.leftConditionType,
|
|
60
59
|
) === PRIMITIVE_TYPE.STRING
|
|
61
60
|
);
|
|
62
61
|
}
|
|
@@ -78,9 +77,7 @@ export class QueryBuilderFilterOperator_EndWith
|
|
|
78
77
|
getDefaultFilterConditionValue(
|
|
79
78
|
filterConditionState: FilterConditionState,
|
|
80
79
|
): ValueSpecification | undefined {
|
|
81
|
-
const propertyType =
|
|
82
|
-
filterConditionState.propertyExpressionState.propertyExpression.func.value
|
|
83
|
-
.genericType.value.rawType;
|
|
80
|
+
const propertyType = filterConditionState.leftConditionType;
|
|
84
81
|
switch (propertyType.path) {
|
|
85
82
|
case PRIMITIVE_TYPE.STRING: {
|
|
86
83
|
return buildDefaultInstanceValue(
|