@finos/legend-application-query 5.0.1 → 5.0.2

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 (93) hide show
  1. package/lib/components/QueryBuilderExplorerPanel.d.ts.map +1 -1
  2. package/lib/components/QueryBuilderExplorerPanel.js +3 -1
  3. package/lib/components/QueryBuilderExplorerPanel.js.map +1 -1
  4. package/lib/components/QueryBuilderFetchStructurePanel.d.ts.map +1 -1
  5. package/lib/components/QueryBuilderFetchStructurePanel.js +39 -7
  6. package/lib/components/QueryBuilderFetchStructurePanel.js.map +1 -1
  7. package/lib/components/QueryBuilderFilterPanel.d.ts.map +1 -1
  8. package/lib/components/QueryBuilderFilterPanel.js +43 -12
  9. package/lib/components/QueryBuilderFilterPanel.js.map +1 -1
  10. package/lib/components/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  11. package/lib/components/QueryBuilderPostFilterPanel.js +12 -3
  12. package/lib/components/QueryBuilderPostFilterPanel.js.map +1 -1
  13. package/lib/components/QueryBuilderPropertySearchPanel.d.ts.map +1 -1
  14. package/lib/components/QueryBuilderPropertySearchPanel.js +2 -1
  15. package/lib/components/QueryBuilderPropertySearchPanel.js.map +1 -1
  16. package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
  17. package/lib/components/QueryBuilderResultPanel.js +11 -7
  18. package/lib/components/QueryBuilderResultPanel.js.map +1 -1
  19. package/lib/index.css +2 -2
  20. package/lib/index.css.map +1 -1
  21. package/lib/package.json +2 -2
  22. package/lib/stores/QueryBuilderExplorerState.d.ts +1 -1
  23. package/lib/stores/QueryBuilderExplorerState.d.ts.map +1 -1
  24. package/lib/stores/QueryBuilderExplorerState.js +13 -3
  25. package/lib/stores/QueryBuilderExplorerState.js.map +1 -1
  26. package/lib/stores/QueryBuilderFilterState.d.ts +7 -1
  27. package/lib/stores/QueryBuilderFilterState.d.ts.map +1 -1
  28. package/lib/stores/QueryBuilderFilterState.js +5 -0
  29. package/lib/stores/QueryBuilderFilterState.js.map +1 -1
  30. package/lib/stores/QueryBuilderOperatorsHelper.d.ts +1 -0
  31. package/lib/stores/QueryBuilderOperatorsHelper.d.ts.map +1 -1
  32. package/lib/stores/QueryBuilderOperatorsHelper.js +28 -1
  33. package/lib/stores/QueryBuilderOperatorsHelper.js.map +1 -1
  34. package/lib/stores/QueryBuilderProjectionState.d.ts +1 -0
  35. package/lib/stores/QueryBuilderProjectionState.d.ts.map +1 -1
  36. package/lib/stores/QueryBuilderProjectionState.js +11 -0
  37. package/lib/stores/QueryBuilderProjectionState.js.map +1 -1
  38. package/lib/stores/QueryBuilderPropertySearchPanelState.js +1 -1
  39. package/lib/stores/QueryBuilderPropertySearchPanelState.js.map +1 -1
  40. package/lib/stores/QueryBuilderResultState.d.ts +5 -2
  41. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  42. package/lib/stores/QueryBuilderResultState.js +19 -7
  43. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  44. package/lib/stores/QueryBuilderState.d.ts +1 -0
  45. package/lib/stores/QueryBuilderState.d.ts.map +1 -1
  46. package/lib/stores/QueryBuilderState.js +3 -0
  47. package/lib/stores/QueryBuilderState.js.map +1 -1
  48. package/lib/stores/filterOperators/QueryBuilderFilterOperator_Equal.d.ts.map +1 -1
  49. package/lib/stores/filterOperators/QueryBuilderFilterOperator_Equal.js +5 -31
  50. package/lib/stores/filterOperators/QueryBuilderFilterOperator_Equal.js.map +1 -1
  51. package/lib/stores/filterOperators/QueryBuilderFilterOperator_GreaterThan.d.ts.map +1 -1
  52. package/lib/stores/filterOperators/QueryBuilderFilterOperator_GreaterThan.js +5 -31
  53. package/lib/stores/filterOperators/QueryBuilderFilterOperator_GreaterThan.js.map +1 -1
  54. package/lib/stores/filterOperators/QueryBuilderFilterOperator_GreaterThanEqual.d.ts.map +1 -1
  55. package/lib/stores/filterOperators/QueryBuilderFilterOperator_GreaterThanEqual.js +5 -31
  56. package/lib/stores/filterOperators/QueryBuilderFilterOperator_GreaterThanEqual.js.map +1 -1
  57. package/lib/stores/filterOperators/QueryBuilderFilterOperator_LessThan.d.ts.map +1 -1
  58. package/lib/stores/filterOperators/QueryBuilderFilterOperator_LessThan.js +5 -32
  59. package/lib/stores/filterOperators/QueryBuilderFilterOperator_LessThan.js.map +1 -1
  60. package/lib/stores/filterOperators/QueryBuilderFilterOperator_LessThanEqual.d.ts.map +1 -1
  61. package/lib/stores/filterOperators/QueryBuilderFilterOperator_LessThanEqual.js +5 -31
  62. package/lib/stores/filterOperators/QueryBuilderFilterOperator_LessThanEqual.js.map +1 -1
  63. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_Equal.d.ts.map +1 -1
  64. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_Equal.js +3 -29
  65. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_Equal.js.map +1 -1
  66. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_GreaterThan.d.ts.map +1 -1
  67. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_GreaterThan.js +4 -30
  68. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_GreaterThan.js.map +1 -1
  69. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_LessThan.d.ts.map +1 -1
  70. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_LessThan.js +4 -30
  71. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_LessThan.js.map +1 -1
  72. package/package.json +9 -9
  73. package/src/components/QueryBuilderExplorerPanel.tsx +3 -1
  74. package/src/components/QueryBuilderFetchStructurePanel.tsx +44 -7
  75. package/src/components/QueryBuilderFilterPanel.tsx +70 -17
  76. package/src/components/QueryBuilderPostFilterPanel.tsx +22 -3
  77. package/src/components/QueryBuilderPropertySearchPanel.tsx +1 -0
  78. package/src/components/QueryBuilderResultPanel.tsx +70 -47
  79. package/src/stores/QueryBuilderExplorerState.ts +17 -3
  80. package/src/stores/QueryBuilderFilterState.ts +7 -0
  81. package/src/stores/QueryBuilderOperatorsHelper.ts +35 -0
  82. package/src/stores/QueryBuilderProjectionState.ts +15 -0
  83. package/src/stores/QueryBuilderPropertySearchPanelState.ts +1 -1
  84. package/src/stores/QueryBuilderResultState.ts +27 -9
  85. package/src/stores/QueryBuilderState.ts +4 -0
  86. package/src/stores/filterOperators/QueryBuilderFilterOperator_Equal.ts +6 -35
  87. package/src/stores/filterOperators/QueryBuilderFilterOperator_GreaterThan.ts +9 -35
  88. package/src/stores/filterOperators/QueryBuilderFilterOperator_GreaterThanEqual.ts +9 -35
  89. package/src/stores/filterOperators/QueryBuilderFilterOperator_LessThan.ts +9 -36
  90. package/src/stores/filterOperators/QueryBuilderFilterOperator_LessThanEqual.ts +9 -35
  91. package/src/stores/postFilterOperators/QueryBuilderPostFilterOperator_Equal.ts +6 -33
  92. package/src/stores/postFilterOperators/QueryBuilderPostFilterOperator_GreaterThan.ts +11 -36
  93. package/src/stores/postFilterOperators/QueryBuilderPostFilterOperator_LessThan.ts +11 -36
@@ -25,6 +25,7 @@ import {
25
25
  CaretDownIcon,
26
26
  ContextMenu,
27
27
  clsx,
28
+ PauseCircleIcon,
28
29
  } from '@finos/legend-art';
29
30
  import { observer } from 'mobx-react-lite';
30
31
  import { flowResult } from 'mobx';
@@ -413,21 +414,25 @@ export const QueryBuilderResultPanel = observer(
413
414
  ],
414
415
  });
415
416
  };
416
- const execute = (): void => {
417
+ const runQuery = (): void => {
417
418
  if (queryParametersState.parameterStates.length) {
418
419
  queryParametersState.parameterValuesEditorState.open(
419
420
  (): Promise<void> =>
420
- flowResult(resultState.execute()).catch(
421
+ flowResult(resultState.runQuery()).catch(
421
422
  applicationStore.alertUnhandledError,
422
423
  ),
423
424
  PARAMETER_SUBMIT_ACTION.EXECUTE,
424
425
  );
425
426
  } else {
426
- flowResult(resultState.execute()).catch(
427
+ flowResult(resultState.runQuery()).catch(
427
428
  applicationStore.alertUnhandledError,
428
429
  );
429
430
  }
430
431
  };
432
+ const cancelQuery = (): void => {
433
+ resultState.setIsRunningQuery(false);
434
+ queryBuilderState.resultState.setQueryRunPromise(undefined);
435
+ };
431
436
  const generatePlan = applicationStore.guardUnhandledError(() =>
432
437
  flowResult(resultState.generatePlan(false)),
433
438
  );
@@ -469,52 +474,65 @@ export const QueryBuilderResultPanel = observer(
469
474
  type="number"
470
475
  value={resultState.previewLimit}
471
476
  onChange={changeLimit}
477
+ disabled={!queryBuilderState.isValidQueryBuilderState()}
472
478
  />
473
479
  </div>
474
480
  )}
475
- <button
476
- className="query-builder__result__execute-btn"
477
- onClick={execute}
478
- disabled={
479
- resultState.isExecutingQuery || resultState.isGeneratingPlan
480
- }
481
- tabIndex={-1}
482
- >
483
- <div className="query-builder__result__execute-btn__label">
484
- <PlayIcon className="query-builder__result__execute-btn__label__icon" />
485
- <div className="query-builder__result__execute-btn__label__title">
486
- Run Query
481
+ {resultState.isRunningQuery ? (
482
+ <button
483
+ className="query-builder__result__stop-btn"
484
+ onClick={cancelQuery}
485
+ tabIndex={-1}
486
+ disabled={!queryBuilderState.isValidQueryBuilderState()}
487
+ >
488
+ <div className="btn--dark btn--caution query-builder__result__stop-btn__label">
489
+ <PauseCircleIcon className="query-builder__result__stop-btn__label__icon" />
490
+ <div className="query-builder__result__stop-btn__label__title">
491
+ Stop
492
+ </div>
487
493
  </div>
488
- </div>
489
- <DropdownMenu
490
- className="query-builder__result__execute-btn__dropdown-btn"
491
- disabled={
492
- resultState.isExecutingQuery || resultState.isGeneratingPlan
493
- }
494
- content={
495
- <MenuContent>
496
- <MenuContentItem
497
- className="query-builder__result__execute-btn__option"
498
- onClick={generatePlan}
499
- >
500
- Generate Plan
501
- </MenuContentItem>
502
- <MenuContentItem
503
- className="query-builder__result__execute-btn__option"
504
- onClick={debugPlanGeneration}
505
- >
506
- Debug
507
- </MenuContentItem>
508
- </MenuContent>
509
- }
510
- menuProps={{
511
- anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
512
- transformOrigin: { vertical: 'top', horizontal: 'right' },
513
- }}
494
+ </button>
495
+ ) : (
496
+ <button
497
+ className="query-builder__result__execute-btn"
498
+ onClick={runQuery}
499
+ tabIndex={-1}
500
+ disabled={!queryBuilderState.isValidQueryBuilderState()}
514
501
  >
515
- <CaretDownIcon />
516
- </DropdownMenu>
517
- </button>
502
+ <div className="query-builder__result__execute-btn__label">
503
+ <PlayIcon className="query-builder__result__execute-btn__label__icon" />
504
+ <div className="query-builder__result__execute-btn__label__title">
505
+ Run Query
506
+ </div>
507
+ </div>
508
+ <DropdownMenu
509
+ className="query-builder__result__execute-btn__dropdown-btn"
510
+ disabled={resultState.isGeneratingPlan}
511
+ content={
512
+ <MenuContent>
513
+ <MenuContentItem
514
+ className="query-builder__result__execute-btn__option"
515
+ onClick={generatePlan}
516
+ >
517
+ Generate Plan
518
+ </MenuContentItem>
519
+ <MenuContentItem
520
+ className="query-builder__result__execute-btn__option"
521
+ onClick={debugPlanGeneration}
522
+ >
523
+ Debug
524
+ </MenuContentItem>
525
+ </MenuContent>
526
+ }
527
+ menuProps={{
528
+ anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
529
+ transformOrigin: { vertical: 'top', horizontal: 'right' },
530
+ }}
531
+ >
532
+ <CaretDownIcon />
533
+ </DropdownMenu>
534
+ </button>
535
+ )}
518
536
  <DropdownMenu
519
537
  className="query-builder__result__export__dropdown"
520
538
  content={
@@ -542,19 +560,24 @@ export const QueryBuilderResultPanel = observer(
542
560
  className="query-builder__result__export__dropdown__label"
543
561
  tabIndex={-1}
544
562
  title="Export"
563
+ disabled={!queryBuilderState.isValidQueryBuilderState()}
545
564
  >
546
565
  Export
547
566
  </button>
548
- <div className="query-builder__result__export__dropdown__trigger">
567
+ <button
568
+ className="query-builder__result__export__dropdown__trigger"
569
+ tabIndex={-1}
570
+ disabled={!queryBuilderState.isValidQueryBuilderState()}
571
+ >
549
572
  <CaretDownIcon />
550
- </div>
573
+ </button>
551
574
  </DropdownMenu>
552
575
  </div>
553
576
  </div>
554
577
  <div className="panel__content">
555
578
  <PanelLoadingIndicator
556
579
  isLoading={
557
- resultState.isExecutingQuery ||
580
+ resultState.isRunningQuery ||
558
581
  resultState.isGeneratingPlan ||
559
582
  resultState.exportDataState.isInProgress
560
583
  }
@@ -50,6 +50,8 @@ import {
50
50
  EntityMappedProperty,
51
51
  Enumeration,
52
52
  DerivedProperty,
53
+ Property,
54
+ Association,
53
55
  } from '@finos/legend-graph';
54
56
  import type { QueryBuilderState } from './QueryBuilderState.js';
55
57
  import {
@@ -342,7 +344,7 @@ export const getQueryBuilderPropertyNodeData = (
342
344
  property: AbstractProperty,
343
345
  parentNode: QueryBuilderExplorerTreeNodeData,
344
346
  modelCoverageAnalysisResult: MappingModelCoverageAnalysisResult,
345
- ): QueryBuilderExplorerTreePropertyNodeData => {
347
+ ): QueryBuilderExplorerTreePropertyNodeData | undefined => {
346
348
  const mappingNodeData = generatePropertyNodeMappingData(
347
349
  property,
348
350
  parentNode.mappingData,
@@ -353,6 +355,16 @@ export const getQueryBuilderPropertyNodeData = (
353
355
  parentNode.isPartOfDerivedPropertyBranch ||
354
356
  (parentNode instanceof QueryBuilderExplorerTreePropertyNodeData &&
355
357
  parentNode.property instanceof DerivedProperty);
358
+ if (
359
+ property instanceof Property &&
360
+ parentNode instanceof QueryBuilderExplorerTreePropertyNodeData &&
361
+ parentNode.property instanceof Property &&
362
+ property._OWNER instanceof Association &&
363
+ parentNode.property._OWNER instanceof Association &&
364
+ parentNode.property._OWNER === property._OWNER
365
+ ) {
366
+ return undefined;
367
+ }
356
368
  const propertyNode = new QueryBuilderExplorerTreePropertyNodeData(
357
369
  `${
358
370
  parentNode instanceof QueryBuilderExplorerTreeRootNodeData
@@ -455,8 +467,10 @@ const getQueryBuilderTreeData = (
455
467
  treeRootNode,
456
468
  modelCoverageAnalysisResult,
457
469
  );
458
- addUniqueEntry(treeRootNode.childrenIds, propertyTreeNodeData.id);
459
- nodes.set(propertyTreeNodeData.id, propertyTreeNodeData);
470
+ if (propertyTreeNodeData) {
471
+ addUniqueEntry(treeRootNode.childrenIds, propertyTreeNodeData.id);
472
+ nodes.set(propertyTreeNodeData.id, propertyTreeNodeData);
473
+ }
460
474
  });
461
475
  rootClass._subclasses.forEach((subclass) => {
462
476
  const subTypeTreeNodeData = getQueryBuilderSubTypeNodeData(
@@ -55,6 +55,7 @@ import {
55
55
  fromGroupOperation,
56
56
  QUERY_BUILDER_GROUP_OPERATION,
57
57
  } from './QueryBuilderOperatorsHelper.js';
58
+ import type { QueryBuilderProjectionColumnDragSource } from './QueryBuilderProjectionState.js';
58
59
 
59
60
  export abstract class QueryBuilderFilterOperator {
60
61
  readonly uuid = uuid();
@@ -95,6 +96,7 @@ export interface QueryBuilderFilterConditionDragSource {
95
96
 
96
97
  export type QueryBuilderFilterDropTarget =
97
98
  | QueryBuilderExplorerTreeDragSource
99
+ | QueryBuilderProjectionColumnDragSource
98
100
  | QueryBuilderFilterConditionDragSource;
99
101
  export type QueryBuilderFilterConditionRearrangeDropTarget =
100
102
  QueryBuilderFilterConditionDragSource;
@@ -407,6 +409,11 @@ export class QueryBuilderFilterState
407
409
  isRearrangingConditions = false;
408
410
  operators: QueryBuilderFilterOperator[] = [];
409
411
  private _suppressClickawayEventListener = false;
412
+ /**
413
+ * This flag is for turning on/off dnd from projection panel to filter panel,
414
+ * and will be leveraged when the concepts of workflows are introduced into query builder.
415
+ */
416
+ allowDnDProjectionToFilter = true;
410
417
 
411
418
  constructor(
412
419
  queryBuilderState: QueryBuilderState,
@@ -29,6 +29,7 @@ import {
29
29
  EnumValueInstanceValue,
30
30
  VariableExpression,
31
31
  AbstractPropertyExpression,
32
+ isSuperType,
32
33
  } from '@finos/legend-graph';
33
34
  import {
34
35
  addUniqueEntry,
@@ -189,3 +190,37 @@ export const isPropertyExpressionChainOptional = (
189
190
  }
190
191
  return isOptional;
191
192
  };
193
+
194
+ export const isTypeCompatibleWithConditionValueType = (
195
+ type: Type | undefined,
196
+ conditionValueType: Type,
197
+ ): boolean => {
198
+ const NUMERIC_PRIMITIVE_TYPES = [
199
+ PRIMITIVE_TYPE.NUMBER,
200
+ PRIMITIVE_TYPE.INTEGER,
201
+ PRIMITIVE_TYPE.DECIMAL,
202
+ PRIMITIVE_TYPE.FLOAT,
203
+ ] as string[];
204
+ const DATE_PRIMITIVE_TYPES = [
205
+ PRIMITIVE_TYPE.DATE,
206
+ PRIMITIVE_TYPE.DATETIME,
207
+ PRIMITIVE_TYPE.STRICTDATE,
208
+ PRIMITIVE_TYPE.LATESTDATE,
209
+ ] as string[];
210
+
211
+ // When changing the return type for LHS, the RHS value should be adjusted accordingly.
212
+ return (
213
+ type !== undefined &&
214
+ // Numeric value is handled loosely because of autoboxing
215
+ // e.g. LHS (integer) = RHS (float) is acceptable
216
+ ((NUMERIC_PRIMITIVE_TYPES.includes(type.path) &&
217
+ NUMERIC_PRIMITIVE_TYPES.includes(conditionValueType.path)) ||
218
+ // Date value is handled loosely as well if the LHS is of type DateTime
219
+ // This is because we would simulate auto-boxing for date by altering the
220
+ // Pure function used for the operation
221
+ // e.g. LHS(DateTime) = RHS(Date) -> we use isOnDay() instead of is()
222
+ DATE_PRIMITIVE_TYPES.includes(type.path) ||
223
+ type === conditionValueType ||
224
+ isSuperType(conditionValueType, type))
225
+ );
226
+ };
@@ -793,4 +793,19 @@ export class QueryBuilderProjectionState {
793
793
  );
794
794
  }
795
795
  }
796
+
797
+ isValidProjectionState(): boolean {
798
+ if (this.queryBuilderState.fetchStructureState.isProjectionMode()) {
799
+ // duplicate columns check
800
+ const hasDuplicatedProjectionColumns = this.columns.some(
801
+ (column) =>
802
+ this.columns.filter((c) => c.columnName === column.columnName)
803
+ .length > 1,
804
+ );
805
+ // no columns check
806
+ const hasNoProjectionColumns = this.columns.length === 0;
807
+ return !hasDuplicatedProjectionColumns && !hasNoProjectionColumns;
808
+ }
809
+ return true;
810
+ }
796
811
  }
@@ -262,7 +262,7 @@ export class QueryBuilderPropertySearchPanelState {
262
262
  ),
263
263
  );
264
264
  if (
265
- propertyTreeNodeData.mappingData.mapped &&
265
+ propertyTreeNodeData?.mappingData.mapped &&
266
266
  !propertyTreeNodeData.isPartOfDerivedPropertyBranch
267
267
  ) {
268
268
  nextLevelPropertyNodes.push(propertyTreeNodeData);
@@ -48,16 +48,18 @@ export class QueryBuilderResultState {
48
48
  queryBuilderState: QueryBuilderState;
49
49
  exportDataState = ActionState.create();
50
50
  previewLimit = DEFAULT_LIMIT;
51
- isExecutingQuery = false;
51
+ isRunningQuery = false;
52
52
  isGeneratingPlan = false;
53
53
  executionResult?: ExecutionResult | undefined;
54
54
  executionPlanState: ExecutionPlanState;
55
55
  executionDuration?: number | undefined;
56
+ queryRunPromise: Promise<ExecutionResult> | undefined = undefined;
56
57
 
57
58
  constructor(queryBuilderState: QueryBuilderState) {
58
59
  makeAutoObservable(this, {
59
60
  queryBuilderState: false,
60
61
  executionPlanState: false,
62
+ setIsRunningQuery: action,
61
63
  setExecutionResult: action,
62
64
  });
63
65
 
@@ -68,16 +70,28 @@ export class QueryBuilderResultState {
68
70
  );
69
71
  }
70
72
 
73
+ setIsRunningQuery = (val: boolean): void => {
74
+ this.isRunningQuery = val;
75
+ };
76
+
71
77
  setExecutionResult = (val: ExecutionResult | undefined): void => {
72
78
  this.executionResult = val;
73
79
  };
80
+
74
81
  setExecutionDuration = (val: number | undefined): void => {
75
82
  this.executionDuration = val;
76
83
  };
84
+
77
85
  setPreviewLimit = (val: number): void => {
78
86
  this.previewLimit = Math.max(1, val);
79
87
  };
80
88
 
89
+ setQueryRunPromise = (
90
+ promise: Promise<ExecutionResult> | undefined,
91
+ ): void => {
92
+ this.queryRunPromise = promise;
93
+ };
94
+
81
95
  buildExecutionRawLambda(): RawLambda {
82
96
  let query: RawLambda;
83
97
  if (this.queryBuilderState.isQuerySupported()) {
@@ -172,9 +186,9 @@ export class QueryBuilderResultState {
172
186
  }
173
187
  }
174
188
 
175
- *execute(): GeneratorFn<void> {
189
+ *runQuery(): GeneratorFn<void> {
176
190
  try {
177
- this.isExecutingQuery = true;
191
+ this.isRunningQuery = true;
178
192
  const mapping = guaranteeNonNullable(
179
193
  this.queryBuilderState.querySetupState.mapping,
180
194
  'Mapping is required to execute query',
@@ -185,15 +199,19 @@ export class QueryBuilderResultState {
185
199
  );
186
200
  const query = this.buildExecutionRawLambda();
187
201
  const startTime = Date.now();
188
- const result =
189
- (yield this.queryBuilderState.graphManagerState.graphManager.executeMapping(
202
+ const promise =
203
+ this.queryBuilderState.graphManagerState.graphManager.executeMapping(
190
204
  query,
191
205
  mapping,
192
206
  runtime,
193
207
  this.queryBuilderState.graphManagerState.graph,
194
- )) as ExecutionResult;
195
- this.setExecutionResult(result);
196
- this.setExecutionDuration(Date.now() - startTime);
208
+ );
209
+ this.setQueryRunPromise(promise);
210
+ const result = (yield promise) as ExecutionResult;
211
+ if (this.queryRunPromise === promise) {
212
+ this.setExecutionResult(result);
213
+ this.setExecutionDuration(Date.now() - startTime);
214
+ }
197
215
  } catch (error) {
198
216
  assertErrorThrown(error);
199
217
  this.queryBuilderState.applicationStore.log.error(
@@ -202,7 +220,7 @@ export class QueryBuilderResultState {
202
220
  );
203
221
  this.queryBuilderState.applicationStore.notifyError(error);
204
222
  } finally {
205
- this.isExecutingQuery = false;
223
+ this.setIsRunningQuery(false);
206
224
  }
207
225
  }
208
226
 
@@ -558,4 +558,8 @@ export class QueryBuilderState {
558
558
  this.fetchStructureState.graphFetchTreeState.initialize();
559
559
  }
560
560
  }
561
+
562
+ isValidQueryBuilderState(): boolean {
563
+ return this.fetchStructureState.projectionState.isValidProjectionState();
564
+ }
561
565
  }
@@ -31,7 +31,6 @@ import {
31
31
  EnumValueExplicitReference,
32
32
  Enumeration,
33
33
  PRIMITIVE_TYPE,
34
- isSuperType,
35
34
  SUPPORTED_FUNCTIONS,
36
35
  buildPrimitiveInstanceValue,
37
36
  } from '@finos/legend-graph';
@@ -46,6 +45,7 @@ import {
46
45
  buildNotExpression,
47
46
  unwrapNotExpression,
48
47
  getNonCollectionValueSpecificationType,
48
+ isTypeCompatibleWithConditionValueType,
49
49
  } from '../QueryBuilderOperatorsHelper.js';
50
50
 
51
51
  export class QueryBuilderFilterOperator_Equal extends QueryBuilderFilterOperator {
@@ -81,41 +81,12 @@ export class QueryBuilderFilterOperator_Equal extends QueryBuilderFilterOperator
81
81
  isCompatibleWithFilterConditionValue(
82
82
  filterConditionState: FilterConditionState,
83
83
  ): boolean {
84
- const propertyType =
84
+ return isTypeCompatibleWithConditionValueType(
85
+ filterConditionState.value
86
+ ? getNonCollectionValueSpecificationType(filterConditionState.value)
87
+ : undefined,
85
88
  filterConditionState.propertyExpressionState.propertyExpression.func
86
- .genericType.value.rawType;
87
- const type = filterConditionState.value
88
- ? getNonCollectionValueSpecificationType(filterConditionState.value)
89
- : undefined;
90
-
91
- const NUMERIC_PRIMITIVE_TYPES = [
92
- PRIMITIVE_TYPE.NUMBER,
93
- PRIMITIVE_TYPE.INTEGER,
94
- PRIMITIVE_TYPE.DECIMAL,
95
- PRIMITIVE_TYPE.FLOAT,
96
- ] as string[];
97
-
98
- const DATE_PRIMITIVE_TYPES = [
99
- PRIMITIVE_TYPE.DATE,
100
- PRIMITIVE_TYPE.DATETIME,
101
- PRIMITIVE_TYPE.STRICTDATE,
102
- PRIMITIVE_TYPE.LATESTDATE,
103
- ] as string[];
104
-
105
- // When changing the return type for LHS, the RHS value should be adjusted accordingly.
106
- return (
107
- type !== undefined &&
108
- // Numeric value is handled loosely because of autoboxing
109
- // e.g. LHS (integer) = RHS (float) is acceptable
110
- ((NUMERIC_PRIMITIVE_TYPES.includes(type.path) &&
111
- NUMERIC_PRIMITIVE_TYPES.includes(propertyType.path)) ||
112
- // Date value is handled loosely as well if the LHS is of type DateTime
113
- // This is because we would simulate auto-boxing for date by altering the
114
- // Pure function used for the operation
115
- // e.g. LHS(DateTime) = RHS(Date) -> we use isOnDay() instead of is()
116
- DATE_PRIMITIVE_TYPES.includes(type.path) ||
117
- type === propertyType ||
118
- isSuperType(propertyType, type))
89
+ .genericType.value.rawType,
119
90
  );
120
91
  }
121
92
 
@@ -24,7 +24,6 @@ import {
24
24
  type SimpleFunctionExpression,
25
25
  type AbstractPropertyExpression,
26
26
  PRIMITIVE_TYPE,
27
- isSuperType,
28
27
  SUPPORTED_FUNCTIONS,
29
28
  buildPrimitiveInstanceValue,
30
29
  } from '@finos/legend-graph';
@@ -35,7 +34,10 @@ import {
35
34
  } from './QueryBuilderFilterOperatorHelper.js';
36
35
  import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '../../QueryBuilder_Const.js';
37
36
  import { generateDefaultValueForPrimitiveType } from '../QueryBuilderValueSpecificationBuilderHelper.js';
38
- import { getNonCollectionValueSpecificationType } from '../QueryBuilderOperatorsHelper.js';
37
+ import {
38
+ getNonCollectionValueSpecificationType,
39
+ isTypeCompatibleWithConditionValueType,
40
+ } from '../QueryBuilderOperatorsHelper.js';
39
41
 
40
42
  export class QueryBuilderFilterOperator_GreaterThan extends QueryBuilderFilterOperator {
41
43
  getLabel(filterConditionState: FilterConditionState): string {
@@ -64,40 +66,12 @@ export class QueryBuilderFilterOperator_GreaterThan extends QueryBuilderFilterOp
64
66
  isCompatibleWithFilterConditionValue(
65
67
  filterConditionState: FilterConditionState,
66
68
  ): boolean {
67
- const propertyType =
69
+ return isTypeCompatibleWithConditionValueType(
70
+ filterConditionState.value
71
+ ? getNonCollectionValueSpecificationType(filterConditionState.value)
72
+ : undefined,
68
73
  filterConditionState.propertyExpressionState.propertyExpression.func
69
- .genericType.value.rawType;
70
- const type = filterConditionState.value
71
- ? getNonCollectionValueSpecificationType(filterConditionState.value)
72
- : undefined;
73
- const NUMERIC_PRIMITIVE_TYPES = [
74
- PRIMITIVE_TYPE.NUMBER,
75
- PRIMITIVE_TYPE.INTEGER,
76
- PRIMITIVE_TYPE.DECIMAL,
77
- PRIMITIVE_TYPE.FLOAT,
78
- ] as string[];
79
-
80
- const DATE_PRIMITIVE_TYPES = [
81
- PRIMITIVE_TYPE.DATE,
82
- PRIMITIVE_TYPE.DATETIME,
83
- PRIMITIVE_TYPE.STRICTDATE,
84
- PRIMITIVE_TYPE.LATESTDATE,
85
- ] as string[];
86
-
87
- // When changing the return type for LHS, the RHS value should be adjusted accordingly.
88
- return (
89
- type !== undefined &&
90
- // Numeric value is handled loosely because of autoboxing
91
- // e.g. LHS (integer) = RHS (float) is acceptable
92
- ((NUMERIC_PRIMITIVE_TYPES.includes(type.path) &&
93
- NUMERIC_PRIMITIVE_TYPES.includes(propertyType.path)) ||
94
- // Date value is handled loosely as well if the LHS is of type DateTime
95
- // This is because we would simulate auto-boxing for date by altering the
96
- // Pure function used for the operation
97
- // e.g. LHS(DateTime) = RHS(Date) -> we use isOnDay() instead of is()
98
- DATE_PRIMITIVE_TYPES.includes(type.path) ||
99
- type === propertyType ||
100
- isSuperType(propertyType, type))
74
+ .genericType.value.rawType,
101
75
  );
102
76
  }
103
77
 
@@ -24,7 +24,6 @@ import {
24
24
  type ValueSpecification,
25
25
  type SimpleFunctionExpression,
26
26
  type AbstractPropertyExpression,
27
- isSuperType,
28
27
  SUPPORTED_FUNCTIONS,
29
28
  buildPrimitiveInstanceValue,
30
29
  } from '@finos/legend-graph';
@@ -35,7 +34,10 @@ import {
35
34
  } from './QueryBuilderFilterOperatorHelper.js';
36
35
  import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '../../QueryBuilder_Const.js';
37
36
  import { generateDefaultValueForPrimitiveType } from '../QueryBuilderValueSpecificationBuilderHelper.js';
38
- import { getNonCollectionValueSpecificationType } from '../QueryBuilderOperatorsHelper.js';
37
+ import {
38
+ getNonCollectionValueSpecificationType,
39
+ isTypeCompatibleWithConditionValueType,
40
+ } from '../QueryBuilderOperatorsHelper.js';
39
41
 
40
42
  export class QueryBuilderFilterOperator_GreaterThanEqual extends QueryBuilderFilterOperator {
41
43
  getLabel(filterConditionState: FilterConditionState): string {
@@ -64,40 +66,12 @@ export class QueryBuilderFilterOperator_GreaterThanEqual extends QueryBuilderFil
64
66
  isCompatibleWithFilterConditionValue(
65
67
  filterConditionState: FilterConditionState,
66
68
  ): boolean {
67
- const propertyType =
69
+ return isTypeCompatibleWithConditionValueType(
70
+ filterConditionState.value
71
+ ? getNonCollectionValueSpecificationType(filterConditionState.value)
72
+ : undefined,
68
73
  filterConditionState.propertyExpressionState.propertyExpression.func
69
- .genericType.value.rawType;
70
- const type = filterConditionState.value
71
- ? getNonCollectionValueSpecificationType(filterConditionState.value)
72
- : undefined;
73
- const NUMERIC_PRIMITIVE_TYPES = [
74
- PRIMITIVE_TYPE.NUMBER,
75
- PRIMITIVE_TYPE.INTEGER,
76
- PRIMITIVE_TYPE.DECIMAL,
77
- PRIMITIVE_TYPE.FLOAT,
78
- ] as string[];
79
-
80
- const DATE_PRIMITIVE_TYPES = [
81
- PRIMITIVE_TYPE.DATE,
82
- PRIMITIVE_TYPE.DATETIME,
83
- PRIMITIVE_TYPE.STRICTDATE,
84
- PRIMITIVE_TYPE.LATESTDATE,
85
- ] as string[];
86
-
87
- // When changing the return type for LHS, the RHS value should be adjusted accordingly.
88
- return (
89
- type !== undefined &&
90
- // Numeric value is handled loosely because of autoboxing
91
- // e.g. LHS (integer) = RHS (float) is acceptable
92
- ((NUMERIC_PRIMITIVE_TYPES.includes(type.path) &&
93
- NUMERIC_PRIMITIVE_TYPES.includes(propertyType.path)) ||
94
- // Date value is handled loosely as well if the LHS is of type DateTime
95
- // This is because we would simulate auto-boxing for date by altering the
96
- // Pure function used for the operation
97
- // e.g. LHS(DateTime) = RHS(Date) -> we use isOnDay() instead of is()
98
- DATE_PRIMITIVE_TYPES.includes(type.path) ||
99
- type === propertyType ||
100
- isSuperType(propertyType, type))
74
+ .genericType.value.rawType,
101
75
  );
102
76
  }
103
77