@finos/legend-query-builder 4.14.71 → 4.14.72

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. package/lib/components/QueryLoader.d.ts.map +1 -1
  2. package/lib/components/QueryLoader.js +12 -34
  3. package/lib/components/QueryLoader.js.map +1 -1
  4. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  5. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +10 -3
  6. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  7. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.d.ts.map +1 -1
  8. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js +2 -2
  9. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js.map +1 -1
  10. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  11. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +6 -2
  12. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  13. package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
  14. package/lib/components/filter/QueryBuilderFilterPanel.js +5 -1
  15. package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
  16. package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts.map +1 -1
  17. package/lib/components/result/tds/QueryBuilderTDSGridResult.js +5 -2
  18. package/lib/components/result/tds/QueryBuilderTDSGridResult.js.map +1 -1
  19. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.d.ts +3 -0
  20. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.d.ts.map +1 -1
  21. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.js +92 -2
  22. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.js.map +1 -1
  23. package/lib/index.css +2 -2
  24. package/lib/index.css.map +1 -1
  25. package/lib/package.json +1 -1
  26. package/lib/stores/QueryBuilderValueSpecificationHelper.d.ts +1 -1
  27. package/lib/stores/QueryBuilderValueSpecificationHelper.d.ts.map +1 -1
  28. package/lib/stores/QueryBuilderValueSpecificationHelper.js +1 -0
  29. package/lib/stores/QueryBuilderValueSpecificationHelper.js.map +1 -1
  30. package/lib/stores/QueryLoaderState.d.ts +8 -6
  31. package/lib/stores/QueryLoaderState.d.ts.map +1 -1
  32. package/lib/stores/QueryLoaderState.js +30 -7
  33. package/lib/stores/QueryLoaderState.js.map +1 -1
  34. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts +4 -1
  35. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts.map +1 -1
  36. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js +22 -11
  37. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
  38. package/lib/stores/filter/QueryBuilderFilterState.d.ts +1 -1
  39. package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
  40. package/lib/stores/filter/QueryBuilderFilterState.js +8 -4
  41. package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
  42. package/package.json +3 -3
  43. package/src/components/QueryLoader.tsx +37 -54
  44. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +24 -2
  45. package/src/components/fetch-structure/QueryBuilderResultModifierPanel.tsx +6 -2
  46. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +10 -2
  47. package/src/components/filter/QueryBuilderFilterPanel.tsx +10 -1
  48. package/src/components/result/tds/QueryBuilderTDSGridResult.tsx +8 -2
  49. package/src/components/result/tds/QueryBuilderTDSSimpleGridResult.tsx +106 -1
  50. package/src/stores/QueryBuilderValueSpecificationHelper.ts +2 -1
  51. package/src/stores/QueryLoaderState.ts +43 -17
  52. package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +39 -10
  53. package/src/stores/filter/QueryBuilderFilterState.ts +11 -3
@@ -61,6 +61,10 @@ import {
61
61
  Dialog,
62
62
  CustomSelectorInput,
63
63
  } from '@finos/legend-art';
64
+ import {
65
+ getTDSColumnCustomizations,
66
+ MAXIMUM_FRACTION_DIGITS,
67
+ } from './QueryBuilderTDSSimpleGridResult.js';
64
68
 
65
69
  export const enum QueryBuilderDataGridCustomAggregationFunction {
66
70
  wavg = 'wavg',
@@ -109,7 +113,7 @@ const QueryResultCellRenderer = observer(
109
113
  const formattedCellValue = (): QueryBuilderTDSResultCellDataType => {
110
114
  if (isNumber(cellValue)) {
111
115
  return Intl.NumberFormat(DEFAULT_LOCALE, {
112
- maximumFractionDigits: 4,
116
+ maximumFractionDigits: MAXIMUM_FRACTION_DIGITS,
113
117
  }).format(Number(cellValue));
114
118
  } else if (isBoolean(cellValue)) {
115
119
  return String(cellValue);
@@ -173,6 +177,7 @@ const getLocalColDefs = (
173
177
  tdsExecutionResult: executionResult,
174
178
  },
175
179
  ...getAggregationTDSColumnCustomizations(executionResult, colName),
180
+ ...getTDSColumnCustomizations(executionResult, colName),
176
181
  } as DataGridColumnDefinition;
177
182
  const persistedColumn = resultState.gridConfig?.columns.find(
178
183
  (c) => c.colId === colName,
@@ -207,8 +212,8 @@ const getFilterTDSColumnCustomizations = (
207
212
  };
208
213
  case PRIMITIVE_TYPE.DECIMAL:
209
214
  case PRIMITIVE_TYPE.INTEGER:
210
- case PRIMITIVE_TYPE.FLOAT:
211
215
  case PRIMITIVE_TYPE.NUMBER:
216
+ case PRIMITIVE_TYPE.FLOAT:
212
217
  return {
213
218
  filter: 'agNumberColumnFilter',
214
219
  };
@@ -241,6 +246,7 @@ const getColDefs = (
241
246
  tdsExecutionResult: executionResult,
242
247
  },
243
248
  ...getFilterTDSColumnCustomizations(executionResult, colName),
249
+ ...getTDSColumnCustomizations(executionResult, colName),
244
250
  }) as DataGridColumnDefinition,
245
251
  );
246
252
 
@@ -19,6 +19,7 @@ import { observer } from 'mobx-react-lite';
19
19
  import type { QueryBuilderState } from '../../../stores/QueryBuilderState.js';
20
20
  import {
21
21
  getTDSRowRankByColumnInAsc,
22
+ PRIMITIVE_TYPE,
22
23
  TDSExecutionResult,
23
24
  } from '@finos/legend-graph';
24
25
  import {
@@ -47,6 +48,109 @@ import type {
47
48
  } from '../../../stores/QueryBuilderResultState.js';
48
49
  import { QUERY_BUILDER_TEST_ID } from '../../../__lib__/QueryBuilderTesting.js';
49
50
 
51
+ export const MAXIMUM_FRACTION_DIGITS = 4;
52
+
53
+ export const getFloatGridColumnCustomHeader = (): string =>
54
+ `<div class="ag-cell-label-container" role="presentation">
55
+ <span
56
+ data-ref="eMenu"
57
+ class="ag-header-icon ag-header-cell-menu-button"
58
+ ></span>
59
+ <span
60
+ data-ref="eFilterButton"
61
+ class="ag-header-icon ag-header-cell-filter-button"
62
+ ></span>
63
+ <div data-ref="eLabel" class="ag-header-cell-label" role="presentation">
64
+ <span
65
+ data-ref="eSortOrder"
66
+ class="ag-header-icon ag-sort-order ag-hidden"
67
+ ></span>
68
+ <span
69
+ data-ref="eSortAsc"
70
+ class="ag-header-icon ag-sort-ascending-icon ag-hidden"
71
+ ></span>
72
+ <span
73
+ data-ref="eSortDesc"
74
+ class="ag-header-icon ag-sort-descending-icon ag-hidden"
75
+ ></span>
76
+ <span
77
+ data-ref="eSortMixed"
78
+ class="ag-header-icon ag-sort-mixed-icon ag-hidden"
79
+ ></span>
80
+ <span
81
+ data-ref="eSortNone"
82
+ class="ag-header-icon ag-sort-none-icon ag-hidden"
83
+ ></span>
84
+ <span
85
+ data-ref="eText"
86
+ class="ag-header-cell-text"
87
+ role="columnheader"
88
+ ></span>
89
+ <span data-ref="eFilter" class="ag-header-icon ag-filter-icon"></span>
90
+ </div>
91
+ <div
92
+ data-testid="query__builder__result__grid__custom-header"
93
+ class="query-builder__result__values__table__custom-header"
94
+ >
95
+ <div
96
+ class="query-builder__result__values__table__custom-header__icon"
97
+ title="some values have been rounded using en-us format in this preview grid (defaults to max 4 decimal places)"
98
+ >
99
+ <svg
100
+ stroke="currentColor"
101
+ fill="currentColor"
102
+ stroke-width="0"
103
+ viewBox="0 0 576 512"
104
+ height="1em"
105
+ width="1em"
106
+ xmlns="http://www.w3.org/2000/svg"
107
+ >
108
+ <path d="M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"></path>
109
+ </svg>
110
+ </div>
111
+ </div>
112
+ </div>`;
113
+
114
+ export const getTDSColumnCustomizations = (
115
+ result: TDSExecutionResult,
116
+ columnName: string,
117
+ ): object => {
118
+ const index = result.builder.columns.findIndex(
119
+ (col) => col.name === columnName,
120
+ );
121
+ if (index >= 0) {
122
+ const columnType = result.builder.columns[index]?.type;
123
+ const colValues = result.result.rows.map((r) => r.values[index]);
124
+ const isTruncated = (
125
+ vals: (string | number | boolean | null | undefined)[],
126
+ ): boolean =>
127
+ Boolean(
128
+ vals.some((val) => {
129
+ if (val) {
130
+ const decimalPart = val.toString().split('.')[1];
131
+ return decimalPart && decimalPart.length > MAXIMUM_FRACTION_DIGITS;
132
+ }
133
+ return false;
134
+ }),
135
+ );
136
+ switch (columnType) {
137
+ case PRIMITIVE_TYPE.NUMBER:
138
+ case PRIMITIVE_TYPE.DECIMAL:
139
+ case PRIMITIVE_TYPE.FLOAT:
140
+ return isTruncated(colValues)
141
+ ? {
142
+ headerComponentParams: {
143
+ template: getFloatGridColumnCustomHeader(),
144
+ },
145
+ }
146
+ : {};
147
+ default:
148
+ return {};
149
+ }
150
+ }
151
+ return {};
152
+ };
153
+
50
154
  const QueryResultCellRenderer = observer(
51
155
  (params: IQueryRendererParamsWithGridType) => {
52
156
  const resultState = params.resultState;
@@ -62,7 +166,7 @@ const QueryResultCellRenderer = observer(
62
166
  const formattedCellValue = (): QueryBuilderTDSResultCellDataType => {
63
167
  if (isNumber(cellValue)) {
64
168
  return Intl.NumberFormat(DEFAULT_LOCALE, {
65
- maximumFractionDigits: 4,
169
+ maximumFractionDigits: MAXIMUM_FRACTION_DIGITS,
66
170
  }).format(Number(cellValue));
67
171
  } else if (isBoolean(cellValue)) {
68
172
  return String(cellValue);
@@ -368,6 +472,7 @@ export const QueryBuilderTDSSimpleGridResult = observer(
368
472
  resizable: true,
369
473
  field: colName,
370
474
  flex: 1,
475
+ ...getTDSColumnCustomizations(executionResult, colName),
371
476
  cellRenderer: QueryResultCellRenderer,
372
477
  cellRendererParams: {
373
478
  resultState: resultState,
@@ -213,7 +213,7 @@ export const isPropertyExpressionChainOptional = (
213
213
 
214
214
  export const isTypeCompatibleForAssignment = (
215
215
  type: Type | undefined,
216
- assignmentType: Type,
216
+ assignmentType: Type | undefined,
217
217
  ): boolean => {
218
218
  const NUMERIC_PRIMITIVE_TYPES = [
219
219
  PRIMITIVE_TYPE.NUMBER,
@@ -231,6 +231,7 @@ export const isTypeCompatibleForAssignment = (
231
231
  // When changing the return type for LHS, the RHS value should be adjusted accordingly.
232
232
  return (
233
233
  type !== undefined &&
234
+ assignmentType !== undefined &&
234
235
  // Numeric value is handled loosely because of autoboxing
235
236
  // e.g. LHS (integer) = RHS (float) is acceptable
236
237
  ((NUMERIC_PRIMITIVE_TYPES.includes(type.path) &&
@@ -19,17 +19,18 @@ import {
19
19
  type GenericLegendApplicationStore,
20
20
  } from '@finos/legend-application';
21
21
  import {
22
- QuerySearchSpecification,
23
- GRAPH_MANAGER_EVENT,
24
22
  type QueryInfo,
25
23
  type LightQuery,
26
24
  type BasicGraphManagerState,
27
25
  type Query,
28
26
  type RawLambda,
27
+ QuerySearchSpecification,
28
+ GRAPH_MANAGER_EVENT,
29
+ QuerySearchSortBy,
29
30
  } from '@finos/legend-graph';
30
31
  import {
31
- ActionState,
32
32
  type GeneratorFn,
33
+ ActionState,
33
34
  assertErrorThrown,
34
35
  guaranteeNonNullable,
35
36
  LogEvent,
@@ -51,7 +52,7 @@ export enum SORT_BY_OPTIONS {
51
52
  SORT_BY_UPDATE = 'Last Updated',
52
53
  }
53
54
 
54
- export type SortByOption = { label: string; value: string };
55
+ export type SortByOption = { label: SORT_BY_OPTIONS; value: SORT_BY_OPTIONS };
55
56
 
56
57
  export class QueryLoaderState {
57
58
  readonly applicationStore: GenericLegendApplicationStore;
@@ -92,7 +93,7 @@ export class QueryLoaderState {
92
93
  showingDefaultQueries = true;
93
94
  showPreviewViewer = false;
94
95
  queryPreviewContent?: QueryInfo | { name: string; content: string };
95
- sortBy = '';
96
+ sortBy = SORT_BY_OPTIONS.SORT_BY_VIEW;
96
97
 
97
98
  constructor(
98
99
  applicationStore: GenericLegendApplicationStore,
@@ -158,10 +159,23 @@ export class QueryLoaderState {
158
159
  this.isCuratedTemplateToggled = val;
159
160
  }
160
161
 
161
- setSortBy(val: string): void {
162
+ setSortBy(val: SORT_BY_OPTIONS): void {
162
163
  this.sortBy = val;
163
164
  }
164
165
 
166
+ getQuerySearchSortBy(sortByValue: string): QuerySearchSortBy | undefined {
167
+ switch (sortByValue) {
168
+ case SORT_BY_OPTIONS.SORT_BY_CREATE:
169
+ return QuerySearchSortBy.SORT_BY_CREATE;
170
+ case SORT_BY_OPTIONS.SORT_BY_UPDATE:
171
+ return QuerySearchSortBy.SORT_BY_UPDATE;
172
+ case SORT_BY_OPTIONS.SORT_BY_VIEW:
173
+ return QuerySearchSortBy.SORT_BY_VIEW;
174
+ default:
175
+ return undefined;
176
+ }
177
+ }
178
+
165
179
  setSearchText(val: string): void {
166
180
  this.searchText = val;
167
181
  }
@@ -171,7 +185,16 @@ export class QueryLoaderState {
171
185
  }
172
186
 
173
187
  setQueries(val: LightQuery[]): void {
174
- this.queries = val.sort((a, b) => a.name.localeCompare(b.name));
188
+ this.queries = val;
189
+ }
190
+
191
+ // search query using search specification
192
+ canPerformAdvancedSearch(searchText: string): boolean {
193
+ return !(
194
+ searchText.length < DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH &&
195
+ !this.showCurrentUserQueriesOnly &&
196
+ Array.from(this.extraFilters.values()).every((value) => value === false)
197
+ );
175
198
  }
176
199
 
177
200
  setShowPreviewViewer(val: boolean): void {
@@ -226,11 +249,7 @@ export class QueryLoaderState {
226
249
  }
227
250
 
228
251
  *searchQueries(searchText: string): GeneratorFn<void> {
229
- if (
230
- searchText.length < DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH &&
231
- !this.showCurrentUserQueriesOnly &&
232
- Array.from(this.extraFilters.values()).every((value) => value === false)
233
- ) {
252
+ if (!this.canPerformAdvancedSearch(searchText)) {
234
253
  // if no search text is specified, use fetch the default queries
235
254
  if (!searchText) {
236
255
  this.showingDefaultQueries = true;
@@ -268,6 +287,10 @@ export class QueryLoaderState {
268
287
  searchSpecification.limit = QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT + 1;
269
288
  searchSpecification.showCurrentUserQueriesOnly =
270
289
  this.showCurrentUserQueriesOnly;
290
+ const querySearchSortBy = this.getQuerySearchSortBy(this.sortBy);
291
+ if (querySearchSortBy) {
292
+ searchSpecification.sortByOption = querySearchSortBy;
293
+ }
271
294
  if (this.queryBuilderState) {
272
295
  Array.from(this.extraFilters.entries()).forEach(([key, value]) => {
273
296
  if (value) {
@@ -288,11 +311,14 @@ export class QueryLoaderState {
288
311
  searchSpecification =
289
312
  this.decorateSearchSpecification?.(searchSpecification) ??
290
313
  searchSpecification;
291
- this.queries = (
292
- (yield this.graphManagerState.graphManager.searchQueries(
293
- searchSpecification,
294
- )) as LightQuery[]
295
- ).sort((a, b) => a.name.localeCompare(b.name));
314
+ this.queries = (yield this.graphManagerState.graphManager.searchQueries(
315
+ searchSpecification,
316
+ )) as LightQuery[];
317
+ if (!querySearchSortBy) {
318
+ this.queries = this.queries.sort((a, b) =>
319
+ a.name.localeCompare(b.name),
320
+ );
321
+ }
296
322
  this.searchQueriesState.pass();
297
323
  } catch (error) {
298
324
  assertErrorThrown(error);
@@ -20,12 +20,12 @@ import {
20
20
  type Type,
21
21
  type ValueSpecification,
22
22
  type ExecutionResult,
23
- type VariableExpression,
24
23
  type SimpleFunctionExpression,
25
24
  observe_ValueSpecification,
26
25
  PrimitiveType,
27
26
  CollectionInstanceValue,
28
27
  InstanceValue,
28
+ VariableExpression,
29
29
  } from '@finos/legend-graph';
30
30
  import {
31
31
  type GeneratorFn,
@@ -74,11 +74,13 @@ import type { QueryBuilderTDSColumnState } from '../QueryBuilderTDSColumnState.j
74
74
  import {
75
75
  getCollectionValueSpecificationType,
76
76
  getNonCollectionValueSpecificationType,
77
+ isTypeCompatibleForAssignment,
77
78
  isValidInstanceValue,
78
79
  isValueExpressionReferencedInValue,
79
80
  } from '../../../QueryBuilderValueSpecificationHelper.js';
80
81
  import { buildtdsPropertyExpressionFromColState } from './operators/QueryBuilderPostFilterOperatorValueSpecificationBuilder.js';
81
82
  import { TDS_COLUMN_GETTER } from '../../../../graph/QueryBuilderMetaModelConst.js';
83
+ import type { QueryBuilderFilterTreeNodeData } from '../../../filter/QueryBuilderFilterState.js';
82
84
 
83
85
  export enum QUERY_BUILDER_POST_FILTER_DND_TYPE {
84
86
  GROUP_CONDITION = 'QUERY_BUILDER_POST_FILTER_DND_TYPE.GROUP_CONDITION',
@@ -1011,15 +1013,45 @@ export class QueryBuilderPostFilterState
1011
1013
  );
1012
1014
  }
1013
1015
 
1016
+ isInvalidValueSpecPostFilterValue(
1017
+ node: QueryBuilderPostFilterTreeNodeData,
1018
+ ): boolean {
1019
+ return (
1020
+ node instanceof QueryBuilderPostFilterTreeConditionNodeData &&
1021
+ node.condition.rightConditionValue instanceof
1022
+ PostFilterValueSpecConditionValueState &&
1023
+ ((node.condition.rightConditionValue.value instanceof InstanceValue &&
1024
+ !isValidInstanceValue(node.condition.rightConditionValue.value)) ||
1025
+ (node.condition.rightConditionValue.value instanceof
1026
+ VariableExpression &&
1027
+ !isTypeCompatibleForAssignment(
1028
+ node.condition.leftConditionValue.getColumnType(),
1029
+ node.condition.rightConditionValue.type,
1030
+ )))
1031
+ );
1032
+ }
1033
+
1034
+ isInvalidTDSColumnPostFilterValue(
1035
+ node: QueryBuilderFilterTreeNodeData,
1036
+ ): boolean {
1037
+ return (
1038
+ node instanceof QueryBuilderPostFilterTreeConditionNodeData &&
1039
+ node.condition.rightConditionValue instanceof
1040
+ PostFilterTDSColumnValueConditionValueState &&
1041
+ !isTypeCompatibleForAssignment(
1042
+ node.condition.leftConditionValue.getColumnType(),
1043
+ node.condition.rightConditionValue.type,
1044
+ )
1045
+ );
1046
+ }
1047
+
1014
1048
  get allValidationIssues(): string[] {
1015
1049
  const validationIssues: string[] = [];
1016
1050
  Array.from(this.nodes.values()).forEach((node) => {
1017
1051
  if (node instanceof QueryBuilderPostFilterTreeConditionNodeData) {
1018
1052
  if (
1019
- node.condition.rightConditionValue instanceof
1020
- PostFilterValueSpecConditionValueState &&
1021
- node.condition.rightConditionValue.value instanceof InstanceValue &&
1022
- !isValidInstanceValue(node.condition.rightConditionValue.value)
1053
+ this.isInvalidValueSpecPostFilterValue(node) ||
1054
+ this.isInvalidTDSColumnPostFilterValue(node)
1023
1055
  ) {
1024
1056
  validationIssues.push(
1025
1057
  `Filter value for ${node.condition.leftConditionValue.columnName} is missing or invalid`,
@@ -1042,11 +1074,8 @@ export class QueryBuilderPostFilterState
1042
1074
  get hasInvalidFilterValues(): boolean {
1043
1075
  return Array.from(this.nodes.values()).some(
1044
1076
  (node) =>
1045
- node instanceof QueryBuilderPostFilterTreeConditionNodeData &&
1046
- node.condition.rightConditionValue instanceof
1047
- PostFilterValueSpecConditionValueState &&
1048
- node.condition.rightConditionValue.value instanceof InstanceValue &&
1049
- !isValidInstanceValue(node.condition.rightConditionValue.value),
1077
+ this.isInvalidValueSpecPostFilterValue(node) ||
1078
+ this.isInvalidTDSColumnPostFilterValue(node),
1050
1079
  );
1051
1080
  }
1052
1081
 
@@ -40,12 +40,12 @@ import {
40
40
  type ExecutionResult,
41
41
  AbstractPropertyExpression,
42
42
  type ValueSpecification,
43
- type VariableExpression,
44
43
  type Type,
45
44
  observe_ValueSpecification,
46
45
  CollectionInstanceValue,
47
46
  InstanceValue,
48
47
  SimpleFunctionExpression,
48
+ VariableExpression,
49
49
  matchFunctionName,
50
50
  } from '@finos/legend-graph';
51
51
  import { DEFAULT_LAMBDA_VARIABLE_NAME } from '../QueryBuilderConfig.js';
@@ -61,6 +61,7 @@ import { QUERY_BUILDER_STATE_HASH_STRUCTURE } from '../QueryBuilderStateHashUtil
61
61
  import {
62
62
  getCollectionValueSpecificationType,
63
63
  getNonCollectionValueSpecificationType,
64
+ isTypeCompatibleForAssignment,
64
65
  isValidInstanceValue,
65
66
  isValueExpressionReferencedInValue,
66
67
  } from '../QueryBuilderValueSpecificationHelper.js';
@@ -1185,8 +1186,15 @@ export class QueryBuilderFilterState
1185
1186
  node instanceof QueryBuilderFilterTreeConditionNodeData &&
1186
1187
  node.condition.rightConditionValue instanceof
1187
1188
  FilterValueSpecConditionValueState &&
1188
- node.condition.rightConditionValue.value instanceof InstanceValue &&
1189
- !isValidInstanceValue(node.condition.rightConditionValue.value)
1189
+ ((node.condition.rightConditionValue.value instanceof InstanceValue &&
1190
+ !isValidInstanceValue(node.condition.rightConditionValue.value)) ||
1191
+ (node.condition.rightConditionValue.value instanceof
1192
+ VariableExpression &&
1193
+ !isTypeCompatibleForAssignment(
1194
+ node.condition.propertyExpressionState.propertyExpression.func.value
1195
+ .genericType.value.rawType,
1196
+ node.condition.rightConditionValue.value.genericType?.value.rawType,
1197
+ )))
1190
1198
  );
1191
1199
  }
1192
1200