@finos/legend-query-builder 4.14.68 → 4.14.70

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 (105) hide show
  1. package/lib/__lib__/QueryBuilderTesting.d.ts +1 -0
  2. package/lib/__lib__/QueryBuilderTesting.d.ts.map +1 -1
  3. package/lib/__lib__/QueryBuilderTesting.js +1 -0
  4. package/lib/__lib__/QueryBuilderTesting.js.map +1 -1
  5. package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts +1 -0
  6. package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts.map +1 -1
  7. package/lib/components/explorer/QueryBuilderExplorerPanel.js +95 -53
  8. package/lib/components/explorer/QueryBuilderExplorerPanel.js.map +1 -1
  9. package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts +4 -0
  10. package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts.map +1 -1
  11. package/lib/components/explorer/QueryBuilderPropertySearchPanel.js +172 -108
  12. package/lib/components/explorer/QueryBuilderPropertySearchPanel.js.map +1 -1
  13. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  14. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +2 -1
  15. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  16. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  17. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +29 -18
  18. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  19. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.d.ts.map +1 -1
  20. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js +13 -4
  21. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js.map +1 -1
  22. package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
  23. package/lib/components/filter/QueryBuilderFilterPanel.js +4 -3
  24. package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
  25. package/lib/components/result/QueryBuilderResultPanel.d.ts +12 -0
  26. package/lib/components/result/QueryBuilderResultPanel.d.ts.map +1 -1
  27. package/lib/components/result/QueryBuilderResultPanel.js +60 -8
  28. package/lib/components/result/QueryBuilderResultPanel.js.map +1 -1
  29. package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts.map +1 -1
  30. package/lib/components/result/tds/QueryBuilderTDSGridResult.js +47 -28
  31. package/lib/components/result/tds/QueryBuilderTDSGridResult.js.map +1 -1
  32. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.d.ts +1 -0
  33. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.d.ts.map +1 -1
  34. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.js +34 -1
  35. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.js.map +1 -1
  36. package/lib/components/shared/QueryBuilderFilterHelper.d.ts.map +1 -1
  37. package/lib/components/shared/QueryBuilderFilterHelper.js +3 -0
  38. package/lib/components/shared/QueryBuilderFilterHelper.js.map +1 -1
  39. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts +11 -0
  40. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts.map +1 -1
  41. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js +6 -3
  42. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js.map +1 -1
  43. package/lib/graph-manager/QueryBuilderConfig.d.ts +4 -0
  44. package/lib/graph-manager/QueryBuilderConfig.d.ts.map +1 -1
  45. package/lib/graph-manager/QueryBuilderConfig.js +5 -0
  46. package/lib/graph-manager/QueryBuilderConfig.js.map +1 -1
  47. package/lib/index.css +2 -2
  48. package/lib/index.css.map +1 -1
  49. package/lib/package.json +1 -1
  50. package/lib/stores/QueryBuilderResultState.d.ts +11 -3
  51. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  52. package/lib/stores/QueryBuilderResultState.js +47 -4
  53. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  54. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.d.ts +4 -0
  55. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.d.ts.map +1 -1
  56. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts +5 -1
  57. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts.map +1 -1
  58. package/lib/stores/explorer/QueryBuilderExplorerState.js +80 -10
  59. package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
  60. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.d.ts +24 -0
  61. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.d.ts.map +1 -0
  62. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js +39 -0
  63. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js.map +1 -0
  64. package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts +8 -4
  65. package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts.map +1 -1
  66. package/lib/stores/explorer/QueryBuilderPropertySearchState.js +204 -114
  67. package/lib/stores/explorer/QueryBuilderPropertySearchState.js.map +1 -1
  68. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts.map +1 -1
  69. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js +8 -1
  70. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
  71. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.d.ts.map +1 -1
  72. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js +12 -1
  73. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js.map +1 -1
  74. package/lib/stores/filter/QueryBuilderFilterState.d.ts +8 -1
  75. package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
  76. package/lib/stores/filter/QueryBuilderFilterState.js +27 -10
  77. package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
  78. package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts +1 -0
  79. package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts.map +1 -1
  80. package/lib/stores/shared/ValueSpecificationEditorHelper.js +6 -2
  81. package/lib/stores/shared/ValueSpecificationEditorHelper.js.map +1 -1
  82. package/package.json +9 -9
  83. package/src/__lib__/QueryBuilderTesting.ts +1 -0
  84. package/src/components/explorer/QueryBuilderExplorerPanel.tsx +228 -115
  85. package/src/components/explorer/QueryBuilderPropertySearchPanel.tsx +618 -388
  86. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +5 -2
  87. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +78 -44
  88. package/src/components/fetch-structure/QueryBuilderTDSWindowPanel.tsx +63 -10
  89. package/src/components/filter/QueryBuilderFilterPanel.tsx +4 -2
  90. package/src/components/result/QueryBuilderResultPanel.tsx +207 -20
  91. package/src/components/result/tds/QueryBuilderTDSGridResult.tsx +57 -38
  92. package/src/components/result/tds/QueryBuilderTDSSimpleGridResult.tsx +43 -0
  93. package/src/components/shared/QueryBuilderFilterHelper.ts +8 -0
  94. package/src/components/shared/QueryBuilderPropertyInfoTooltip.tsx +13 -3
  95. package/src/graph-manager/QueryBuilderConfig.ts +6 -0
  96. package/src/stores/QueryBuilderResultState.ts +64 -10
  97. package/src/stores/QueryBuilderValueSpecificationBuilderHelper.ts +5 -0
  98. package/src/stores/explorer/QueryBuilderExplorerState.ts +112 -8
  99. package/src/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.ts +46 -0
  100. package/src/stores/explorer/QueryBuilderPropertySearchState.ts +280 -142
  101. package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +8 -1
  102. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.ts +15 -2
  103. package/src/stores/filter/QueryBuilderFilterState.ts +34 -11
  104. package/src/stores/shared/ValueSpecificationEditorHelper.ts +9 -1
  105. package/tsconfig.json +1 -0
@@ -61,6 +61,7 @@ import {
61
61
  Dialog,
62
62
  CustomSelectorInput,
63
63
  } from '@finos/legend-art';
64
+ import { getFloatGridColumnCustomHeader } from './QueryBuilderTDSSimpleGridResult.js';
64
65
 
65
66
  export const enum QueryBuilderDataGridCustomAggregationFunction {
66
67
  wavg = 'wavg',
@@ -87,13 +88,20 @@ const getAggregationTDSColumnCustomizations = (
87
88
  filter: 'agDateColumnFilter',
88
89
  allowedAggFuncs: ['count'],
89
90
  };
90
- case PRIMITIVE_TYPE.DECIMAL:
91
91
  case PRIMITIVE_TYPE.NUMBER:
92
92
  case PRIMITIVE_TYPE.INTEGER:
93
+ return {
94
+ filter: 'agNumberColumnFilter',
95
+ allowedAggFuncs: ['count', 'sum', 'max', 'min', 'avg', 'wavg'],
96
+ };
97
+ case PRIMITIVE_TYPE.DECIMAL:
93
98
  case PRIMITIVE_TYPE.FLOAT:
94
99
  return {
95
100
  filter: 'agNumberColumnFilter',
96
101
  allowedAggFuncs: ['count', 'sum', 'max', 'min', 'avg', 'wavg'],
102
+ headerComponentParams: {
103
+ template: getFloatGridColumnCustomHeader(columnName),
104
+ },
97
105
  };
98
106
  default:
99
107
  return {
@@ -102,42 +110,6 @@ const getAggregationTDSColumnCustomizations = (
102
110
  }
103
111
  };
104
112
 
105
- const getLocalColDefs = (
106
- executionResult: TDSExecutionResult,
107
- resultState: QueryBuilderResultState,
108
- ): DataGridColumnDefinition<
109
- QueryBuilderTDSRowDataType,
110
- QueryBuilderTDSResultCellDataType
111
- >[] =>
112
- executionResult.result.columns.map((colName) => {
113
- const col = {
114
- minWidth: 50,
115
- sortable: true,
116
- resizable: true,
117
- field: colName,
118
- flex: 1,
119
- enablePivot: true,
120
- enableRowGroup: true,
121
- enableValue: true,
122
- ...getAggregationTDSColumnCustomizations(executionResult, colName),
123
- } as DataGridColumnDefinition;
124
- const persistedColumn = resultState.gridConfig?.columns.find(
125
- (c) => c.colId === colName,
126
- );
127
- if (persistedColumn) {
128
- if (persistedColumn.width) {
129
- col.width = persistedColumn.width;
130
- }
131
- col.pinned = persistedColumn.pinned ?? null;
132
- col.rowGroup = persistedColumn.rowGroup ?? false;
133
- col.rowGroupIndex = persistedColumn.rowGroupIndex ?? null;
134
- col.aggFunc = persistedColumn.aggFunc ?? null;
135
- col.pivot = persistedColumn.pivot ?? false;
136
- col.hide = persistedColumn.hide ?? false;
137
- }
138
- return col;
139
- });
140
-
141
113
  const QueryResultCellRenderer = observer(
142
114
  (params: IQueryRendererParamsWithGridType) => {
143
115
  const resultState = params.resultState;
@@ -186,6 +158,47 @@ const QueryResultCellRenderer = observer(
186
158
  },
187
159
  );
188
160
 
161
+ const getLocalColDefs = (
162
+ executionResult: TDSExecutionResult,
163
+ resultState: QueryBuilderResultState,
164
+ ): DataGridColumnDefinition<
165
+ QueryBuilderTDSRowDataType,
166
+ QueryBuilderTDSResultCellDataType
167
+ >[] =>
168
+ executionResult.result.columns.map((colName) => {
169
+ const col = {
170
+ minWidth: 50,
171
+ sortable: true,
172
+ resizable: true,
173
+ field: colName,
174
+ flex: 1,
175
+ enablePivot: true,
176
+ enableRowGroup: true,
177
+ enableValue: true,
178
+ cellRenderer: QueryResultCellRenderer,
179
+ cellRendererParams: {
180
+ resultState: resultState,
181
+ tdsExecutionResult: executionResult,
182
+ },
183
+ ...getAggregationTDSColumnCustomizations(executionResult, colName),
184
+ } as DataGridColumnDefinition;
185
+ const persistedColumn = resultState.gridConfig?.columns.find(
186
+ (c) => c.colId === colName,
187
+ );
188
+ if (persistedColumn) {
189
+ if (persistedColumn.width) {
190
+ col.width = persistedColumn.width;
191
+ }
192
+ col.pinned = persistedColumn.pinned ?? null;
193
+ col.rowGroup = persistedColumn.rowGroup ?? false;
194
+ col.rowGroupIndex = persistedColumn.rowGroupIndex ?? null;
195
+ col.aggFunc = persistedColumn.aggFunc ?? null;
196
+ col.pivot = persistedColumn.pivot ?? false;
197
+ col.hide = persistedColumn.hide ?? false;
198
+ }
199
+ return col;
200
+ });
201
+
189
202
  const getFilterTDSColumnCustomizations = (
190
203
  result: TDSExecutionResult,
191
204
  columnName: string,
@@ -202,11 +215,17 @@ const getFilterTDSColumnCustomizations = (
202
215
  };
203
216
  case PRIMITIVE_TYPE.DECIMAL:
204
217
  case PRIMITIVE_TYPE.INTEGER:
205
- case PRIMITIVE_TYPE.FLOAT:
206
218
  case PRIMITIVE_TYPE.NUMBER:
207
219
  return {
208
220
  filter: 'agNumberColumnFilter',
209
221
  };
222
+ case PRIMITIVE_TYPE.FLOAT:
223
+ return {
224
+ filter: 'agNumberColumnFilter',
225
+ headerComponentParams: {
226
+ template: getFloatGridColumnCustomHeader(columnName),
227
+ },
228
+ };
210
229
  default:
211
230
  // we default all other columns to use filter true which defaults to set filters
212
231
  return {
@@ -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,47 @@ import type {
47
48
  } from '../../../stores/QueryBuilderResultState.js';
48
49
  import { QUERY_BUILDER_TEST_ID } from '../../../__lib__/QueryBuilderTesting.js';
49
50
 
51
+ export const getFloatGridColumnCustomHeader = (
52
+ columnName: string,
53
+ ): string => ` <div data-testid="query__builder__result__grid__custom-header" class="query-builder__result__values__table__custom-header">
54
+ <div>${columnName}</div>
55
+ <div
56
+ class="query-builder__result__stale-status__icon"
57
+ title="some values have been rounded using en-us format in this preview grid (defaults to max 4 decimal places)"
58
+ >
59
+ <svg
60
+ stroke="currentColor"
61
+ fill="currentColor"
62
+ stroke-width="0"
63
+ viewBox="0 0 576 512"
64
+ height="1em"
65
+ width="1em"
66
+ xmlns="http://www.w3.org/2000/svg"
67
+ >
68
+ <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>
69
+ </svg>
70
+ </div>
71
+ </div>`;
72
+
73
+ const getTDSColumnCustomizations = (
74
+ result: TDSExecutionResult,
75
+ columnName: string,
76
+ ): object => {
77
+ const columnType = result.builder.columns.find(
78
+ (col) => col.name === columnName,
79
+ )?.type;
80
+ switch (columnType) {
81
+ case PRIMITIVE_TYPE.FLOAT:
82
+ return {
83
+ headerComponentParams: {
84
+ template: getFloatGridColumnCustomHeader(columnName),
85
+ },
86
+ };
87
+ default:
88
+ return {};
89
+ }
90
+ };
91
+
50
92
  const QueryResultCellRenderer = observer(
51
93
  (params: IQueryRendererParamsWithGridType) => {
52
94
  const resultState = params.resultState;
@@ -368,6 +410,7 @@ export const QueryBuilderTDSSimpleGridResult = observer(
368
410
  resizable: true,
369
411
  field: colName,
370
412
  flex: 1,
413
+ ...getTDSColumnCustomizations(executionResult, colName),
371
414
  cellRenderer: QueryResultCellRenderer,
372
415
  cellRendererParams: {
373
416
  resultState: resultState,
@@ -28,6 +28,10 @@ import {
28
28
  QUERY_BUILDER_VARIABLE_DND_TYPE,
29
29
  type QueryBuilderVariableDragSource,
30
30
  } from './BasicValueSpecificationEditor.js';
31
+ import {
32
+ QUERY_BUILDER_WINDOW_COLUMN_DND_TYPE,
33
+ type QueryBuilderWindowColumnDragSource,
34
+ } from '../../stores/fetch-structure/tds/window/QueryBuilderWindowState.js';
31
35
 
32
36
  export const getDNDItemType = (
33
37
  item: QueryBuilderFilterValueDropTarget,
@@ -45,6 +49,10 @@ export const getDNDItemType = (
45
49
  case QUERY_BUILDER_VARIABLE_DND_TYPE:
46
50
  return (item as QueryBuilderVariableDragSource).variable.genericType
47
51
  ?.value.rawType;
52
+ case QUERY_BUILDER_WINDOW_COLUMN_DND_TYPE:
53
+ return (
54
+ item as QueryBuilderWindowColumnDragSource
55
+ ).columnState.getColumnType();
48
56
  default:
49
57
  return undefined;
50
58
  }
@@ -117,7 +117,7 @@ export const QueryBuilderTaggedValueInfoTooltip: React.FC<{
117
117
  );
118
118
  };
119
119
 
120
- const QueryBuilderBaseInfoTooltip: React.FC<{
120
+ export const QueryBuilderBaseInfoTooltip: React.FC<{
121
121
  title: string;
122
122
  data: {
123
123
  label: string;
@@ -133,7 +133,10 @@ const QueryBuilderBaseInfoTooltip: React.FC<{
133
133
  const [open, setIsOpen] = useState(false);
134
134
 
135
135
  return (
136
- <ClickAwayListener onClickAway={() => setIsOpen(false)}>
136
+ <ClickAwayListener
137
+ onClickAway={() => setIsOpen(false)}
138
+ mouseEvent="onMouseDown"
139
+ >
137
140
  <div>
138
141
  <Tooltip
139
142
  arrow={true}
@@ -172,7 +175,14 @@ const QueryBuilderBaseInfoTooltip: React.FC<{
172
175
  </div>
173
176
  }
174
177
  >
175
- <div onClick={() => setIsOpen(true)}>{children}</div>
178
+ <div
179
+ onClick={(event: React.MouseEvent) => {
180
+ setIsOpen(!open);
181
+ event.stopPropagation();
182
+ }}
183
+ >
184
+ {children}
185
+ </div>
176
186
  </Tooltip>
177
187
  </div>
178
188
  </ClickAwayListener>
@@ -33,11 +33,17 @@ export class QueryBuilderConfig {
33
33
  */
34
34
  legendAIServiceURL = '';
35
35
 
36
+ /**
37
+ * This is the URL of the zipkin trace
38
+ */
39
+ zipkinTraceBaseURL = '';
40
+
36
41
  static readonly serialization = new SerializationFactory(
37
42
  createModelSchema(QueryBuilderConfig, {
38
43
  TEMPORARY__disableQueryBuilderChat: optional(primitive()),
39
44
  TEMPORARY__enableGridEnterpriseMode: optional(primitive()),
40
45
  legendAIServiceURL: optional(primitive()),
46
+ zipkinTraceBaseURL: optional(primitive()),
41
47
  }),
42
48
  );
43
49
  }
@@ -17,10 +17,10 @@
17
17
  import { action, flow, makeObservable, observable } from 'mobx';
18
18
  import {
19
19
  type GeneratorFn,
20
+ type ContentType,
20
21
  assertErrorThrown,
21
22
  LogEvent,
22
23
  guaranteeNonNullable,
23
- type ContentType,
24
24
  ActionState,
25
25
  StopWatch,
26
26
  getContentTypeFileExtension,
@@ -32,11 +32,13 @@ import {
32
32
  type RawLambda,
33
33
  type EXECUTION_SERIALIZATION_FORMAT,
34
34
  type QueryGridConfig,
35
+ type ExecutionResultWithMetadata,
35
36
  GRAPH_MANAGER_EVENT,
36
37
  buildRawLambdaFromLambdaFunction,
37
38
  reportGraphAnalytics,
39
+ TDSExecutionResult,
40
+ V1_ZIPKIN_TRACE_HEADER,
38
41
  } from '@finos/legend-graph';
39
-
40
42
  import { buildLambdaFunction } from './QueryBuilderValueSpecificationBuilder.js';
41
43
  import {
42
44
  buildExecutionParameterValues,
@@ -49,6 +51,7 @@ import { ExecutionPlanState } from './execution-plan/ExecutionPlanState.js';
49
51
  import type { DataGridColumnState } from '@finos/legend-lego/data-grid';
50
52
  import { downloadStream } from '@finos/legend-application';
51
53
  import { QueryBuilderDataGridCustomAggregationFunction } from '../components/result/tds/QueryBuilderTDSGridResult.js';
54
+ import { QueryBuilderTDSState } from './fetch-structure/tds/QueryBuilderTDSState.js';
52
55
 
53
56
  export const DEFAULT_LIMIT = 1000;
54
57
 
@@ -125,10 +128,13 @@ export class QueryBuilderResultState {
125
128
  isRunningQuery = false;
126
129
  isGeneratingPlan = false;
127
130
  executionResult?: ExecutionResult | undefined;
131
+ isExecutionResultOverflowing = false;
128
132
  executionDuration?: number | undefined;
133
+ executionTraceId?: string;
129
134
  latestRunHashCode?: string | undefined;
130
- queryRunPromise: Promise<ExecutionResult> | undefined = undefined;
135
+ queryRunPromise: Promise<ExecutionResultWithMetadata> | undefined = undefined;
131
136
  isQueryUsageViewerOpened = false;
137
+ executionError: Error | string | undefined;
132
138
 
133
139
  selectedCells: QueryBuilderTDSResultCellData[];
134
140
  mousedOverCell: QueryBuilderTDSResultCellData | null = null;
@@ -140,6 +146,7 @@ export class QueryBuilderResultState {
140
146
  constructor(queryBuilderState: QueryBuilderState) {
141
147
  makeObservable(this, {
142
148
  executionResult: observable,
149
+ executionTraceId: observable,
143
150
  previewLimit: observable,
144
151
  executionDuration: observable,
145
152
  latestRunHashCode: observable,
@@ -150,13 +157,16 @@ export class QueryBuilderResultState {
150
157
  isRunningQuery: observable,
151
158
  isSelectingCells: observable,
152
159
  isQueryUsageViewerOpened: observable,
160
+ isExecutionResultOverflowing: observable,
153
161
  gridConfig: observable,
154
162
  wavgAggregationState: observable,
163
+ executionError: observable,
155
164
  setGridConfig: action,
156
165
  setWavgAggregationState: action,
157
166
  setIsSelectingCells: action,
158
167
  setIsRunningQuery: action,
159
168
  setExecutionResult: action,
169
+ setExecutionTraceId: action,
160
170
  setExecutionDuration: action,
161
171
  setPreviewLimit: action,
162
172
  addSelectedCell: action,
@@ -164,8 +174,10 @@ export class QueryBuilderResultState {
164
174
  setMouseOverCell: action,
165
175
  setQueryRunPromise: action,
166
176
  setIsQueryUsageViewerOpened: action,
177
+ setIsExecutionResultOverflowing: action,
167
178
  handlePreConfiguredGridConfig: action,
168
179
  updatePreviewLimitInConfig: action,
180
+ setExecutionError: action,
169
181
  exportData: flow,
170
182
  runQuery: flow,
171
183
  cancelQuery: flow,
@@ -204,6 +216,10 @@ export class QueryBuilderResultState {
204
216
  this.executionResult = val;
205
217
  }
206
218
 
219
+ setExecutionTraceId(val: string): void {
220
+ this.executionTraceId = val;
221
+ }
222
+
207
223
  setExecutionDuration(val: number | undefined): void {
208
224
  this.executionDuration = val;
209
225
  }
@@ -224,7 +240,9 @@ export class QueryBuilderResultState {
224
240
  this.mousedOverCell = val;
225
241
  }
226
242
 
227
- setQueryRunPromise(promise: Promise<ExecutionResult> | undefined): void {
243
+ setQueryRunPromise(
244
+ promise: Promise<ExecutionResultWithMetadata> | undefined,
245
+ ): void {
228
246
  this.queryRunPromise = promise;
229
247
  }
230
248
 
@@ -232,12 +250,44 @@ export class QueryBuilderResultState {
232
250
  this.isQueryUsageViewerOpened = val;
233
251
  }
234
252
 
253
+ setExecutionError(val: Error | string | undefined): void {
254
+ this.executionError = val;
255
+ }
256
+
257
+ setIsExecutionResultOverflowing(val: boolean): void {
258
+ this.isExecutionResultOverflowing = val;
259
+ }
260
+
235
261
  updatePreviewLimitInConfig(): void {
236
262
  if (this.gridConfig) {
237
263
  this.gridConfig.previewLimit = this.previewLimit;
238
264
  }
239
265
  }
240
266
 
267
+ getExecutionResultLimit = (): number =>
268
+ Math.min(
269
+ this.queryBuilderState.fetchStructureState.implementation instanceof
270
+ QueryBuilderTDSState &&
271
+ this.queryBuilderState.fetchStructureState.implementation
272
+ .resultSetModifierState.limit
273
+ ? this.queryBuilderState.fetchStructureState.implementation
274
+ .resultSetModifierState.limit
275
+ : Number.MAX_SAFE_INTEGER,
276
+ this.previewLimit,
277
+ );
278
+
279
+ processExecutionResult = (result: ExecutionResult): void => {
280
+ this.setIsExecutionResultOverflowing(false);
281
+ if (result instanceof TDSExecutionResult) {
282
+ const resultLimit = this.getExecutionResultLimit();
283
+ if (result.result.rows.length > resultLimit) {
284
+ this.setIsExecutionResultOverflowing(true);
285
+ result.result.rows = result.result.rows.slice(0, resultLimit);
286
+ }
287
+ }
288
+ this.setExecutionResult(result);
289
+ };
290
+
241
291
  processWeightedColumnPairsMap(
242
292
  config: QueryGridConfig,
243
293
  ): Map<string, string> | undefined {
@@ -421,7 +471,9 @@ export class QueryBuilderResultState {
421
471
  this.queryBuilderState.executionContextState.runtimeValue,
422
472
  `Runtime is required to execute query`,
423
473
  );
424
- const query = this.buildExecutionRawLambda();
474
+ const query = this.buildExecutionRawLambda({
475
+ withDataOverflowCheck: true,
476
+ });
425
477
  const parameterValues = buildExecutionParameterValues(
426
478
  this.queryBuilderState.parametersState.parameterStates,
427
479
  this.queryBuilderState.graphManagerState,
@@ -444,13 +496,17 @@ export class QueryBuilderResultState {
444
496
  {
445
497
  parameterValues,
446
498
  convertUnsafeNumbersToString: true,
499
+ preservedResponseHeadersList: [V1_ZIPKIN_TRACE_HEADER],
447
500
  },
448
501
  );
449
502
 
450
503
  this.setQueryRunPromise(promise);
451
- const result = (yield promise) as ExecutionResult;
504
+ const result = (yield promise) as ExecutionResultWithMetadata;
452
505
  if (this.queryRunPromise === promise) {
453
- this.setExecutionResult(result);
506
+ this.processExecutionResult(result.executionResult);
507
+ if (result.executionTraceId) {
508
+ this.setExecutionTraceId(result.executionTraceId);
509
+ }
454
510
  this.latestRunHashCode = currentHashCode;
455
511
  this.setExecutionDuration(stopWatch.elapsed);
456
512
 
@@ -479,9 +535,7 @@ export class QueryBuilderResultState {
479
535
  LogEvent.create(GRAPH_MANAGER_EVENT.EXECUTION_FAILURE),
480
536
  error,
481
537
  );
482
- this.queryBuilderState.applicationStore.notificationService.notifyError(
483
- error,
484
- );
538
+ this.setExecutionError(error);
485
539
  }
486
540
  } finally {
487
541
  this.setIsRunningQuery(false);
@@ -210,4 +210,9 @@ export type LambdaFunctionBuilderOption = {
210
210
  * typed in engine. This is still an experimental feature, hence we should only enable this flag when user wants to enable this directly.
211
211
  */
212
212
  useTypedRelationFunctions?: boolean | undefined;
213
+
214
+ /**
215
+ * Set this flag to `true` when you want to execute a query that exceeds the limit to check for additional data in the database.
216
+ */
217
+ withDataOverflowCheck?: boolean | undefined;
213
218
  };
@@ -118,8 +118,10 @@ export abstract class QueryBuilderExplorerTreeNodeData implements TreeNodeData {
118
118
  ) {
119
119
  makeObservable(this, {
120
120
  isHighlighting: observable,
121
+ isOpen: observable,
121
122
  isSelected: observable,
122
123
  setIsHighlighting: action,
124
+ setIsOpen: action,
123
125
  setIsSelected: action,
124
126
  });
125
127
 
@@ -136,6 +138,10 @@ export abstract class QueryBuilderExplorerTreeNodeData implements TreeNodeData {
136
138
  this.isSelected = val;
137
139
  }
138
140
 
141
+ setIsOpen(val: boolean | undefined): void {
142
+ this.isOpen = val;
143
+ }
144
+
139
145
  setIsHighlighting(val: boolean | undefined): void {
140
146
  this.isHighlighting = val;
141
147
  }
@@ -650,15 +656,18 @@ export class QueryBuilderExplorerPreviewDataState {
650
656
  isGeneratingPreviewData = false;
651
657
  propertyName = '(unknown)';
652
658
  previewData?: QueryBuilderPreviewData | undefined;
659
+ previewDataAbortController?: AbortController | undefined;
653
660
 
654
661
  constructor() {
655
662
  makeObservable(this, {
656
663
  previewData: observable.ref,
657
664
  isGeneratingPreviewData: observable,
658
665
  propertyName: observable,
666
+ previewDataAbortController: observable,
659
667
  setPropertyName: action,
660
668
  setIsGeneratingPreviewData: action,
661
669
  setPreviewData: action,
670
+ setPreviewDataAbortController: action,
662
671
  });
663
672
  }
664
673
 
@@ -673,6 +682,10 @@ export class QueryBuilderExplorerPreviewDataState {
673
682
  setPreviewData(val: QueryBuilderPreviewData | undefined): void {
674
683
  this.previewData = val;
675
684
  }
685
+
686
+ setPreviewDataAbortController(val: AbortController | undefined): void {
687
+ this.previewDataAbortController = val;
688
+ }
676
689
  }
677
690
 
678
691
  export class QueryBuilderExplorerState {
@@ -754,21 +767,99 @@ export class QueryBuilderExplorerState {
754
767
  );
755
768
  }
756
769
 
757
- highlightTreeNode(key: string): void {
758
- const nodeToHighlight = this.treeData?.nodes.get(key);
759
- if (nodeToHighlight instanceof QueryBuilderExplorerTreePropertyNodeData) {
770
+ generateOpenNodeChildren(node: QueryBuilderExplorerTreeNodeData): void {
771
+ if (
772
+ node.isOpen &&
773
+ (node instanceof QueryBuilderExplorerTreePropertyNodeData ||
774
+ node instanceof QueryBuilderExplorerTreeSubTypeNodeData) &&
775
+ node.type instanceof Class
776
+ ) {
777
+ (node instanceof QueryBuilderExplorerTreeSubTypeNodeData
778
+ ? getAllOwnClassProperties(node.type)
779
+ : getAllClassProperties(node.type).concat(
780
+ getAllClassDerivedProperties(node.type),
781
+ )
782
+ ).forEach((property) => {
783
+ const propertyTreeNodeData = getQueryBuilderPropertyNodeData(
784
+ property,
785
+ node,
786
+ guaranteeNonNullable(this.mappingModelCoverageAnalysisResult),
787
+ );
788
+ if (propertyTreeNodeData) {
789
+ this.nonNullableTreeData.nodes.set(
790
+ propertyTreeNodeData.id,
791
+ propertyTreeNodeData,
792
+ );
793
+ }
794
+ });
795
+ node.type._subclasses.forEach((subclass) => {
796
+ const subTypeTreeNodeData = getQueryBuilderSubTypeNodeData(
797
+ subclass,
798
+ node,
799
+ guaranteeNonNullable(this.mappingModelCoverageAnalysisResult),
800
+ );
801
+ this.nonNullableTreeData.nodes.set(
802
+ subTypeTreeNodeData.id,
803
+ subTypeTreeNodeData,
804
+ );
805
+ });
806
+ this.refreshTree();
807
+ }
808
+ }
809
+
810
+ highlightTreeNode(nodeId: string): void {
811
+ // If the node doesn't yet exist in the explorer tree,
812
+ // we need to open all the parent nodes of the node and
813
+ // generate their children.
814
+ if (this.nonNullableTreeData.nodes.get(nodeId) === undefined) {
815
+ const parentNodeIdElements: string[][] = nodeId
816
+ .split('@')
817
+ .map((subpath) => subpath.split('.'));
818
+ // remove last element of final subpath, as it is the node id and not a parent
819
+ if (
820
+ parentNodeIdElements.length > 0 &&
821
+ parentNodeIdElements[parentNodeIdElements.length - 1] !== undefined
822
+ ) {
823
+ parentNodeIdElements[parentNodeIdElements.length - 1]!.pop();
824
+ }
825
+
826
+ let currentNodeId = '';
827
+
828
+ parentNodeIdElements.forEach((subpath) => {
829
+ subpath.forEach((element, index) => {
830
+ currentNodeId += `${index > 0 ? '.' : ''}${element}`;
831
+ const currentNode = this.nonNullableTreeData.nodes.get(currentNodeId);
832
+ if (currentNode) {
833
+ currentNode.setIsOpen(true);
834
+ this.generateOpenNodeChildren(currentNode);
835
+ }
836
+ });
837
+ currentNodeId += '@';
838
+ });
839
+ }
840
+
841
+ // All parent nodes should be created now, so we can get the node to highlight.
842
+ const nodeToHighlight = this.nonNullableTreeData.nodes.get(nodeId);
843
+
844
+ // If we didn't need to open and create the parent nodes above, we will
845
+ // open the parent nodes here in case they are closed. Then, we will highlight
846
+ // and scroll to the node.
847
+ if (
848
+ nodeToHighlight instanceof QueryBuilderExplorerTreePropertyNodeData ||
849
+ nodeToHighlight instanceof QueryBuilderExplorerTreeSubTypeNodeData
850
+ ) {
760
851
  let nodeToOpen: QueryBuilderExplorerTreeNodeData | null =
761
- this.treeData?.nodes.get(nodeToHighlight.parentId) ?? null;
852
+ this.nonNullableTreeData.nodes.get(nodeToHighlight.parentId) ?? null;
762
853
  while (nodeToOpen !== null) {
763
854
  if (!nodeToOpen.isOpen) {
764
- nodeToOpen.isOpen = true;
855
+ nodeToOpen.setIsOpen(true);
765
856
  }
766
857
  nodeToOpen =
767
- nodeToOpen instanceof QueryBuilderExplorerTreePropertyNodeData
768
- ? (this.treeData?.nodes.get(nodeToOpen.parentId) ?? null)
858
+ nodeToOpen instanceof QueryBuilderExplorerTreePropertyNodeData ||
859
+ nodeToOpen instanceof QueryBuilderExplorerTreeSubTypeNodeData
860
+ ? (this.nonNullableTreeData.nodes.get(nodeToOpen.parentId) ?? null)
769
861
  : null;
770
862
  }
771
- this.refreshTree();
772
863
  nodeToHighlight.setIsHighlighting(true);
773
864
  // scrollIntoView must be called in a setTimeout because it must happen after
774
865
  // the tree nodes are recursively opened and the tree is refreshed.
@@ -859,6 +950,7 @@ export class QueryBuilderExplorerState {
859
950
  this,
860
951
  );
861
952
  const propertyType = node.property.genericType.value.rawType;
953
+ this.previewDataState.setPreviewDataAbortController(new AbortController());
862
954
  try {
863
955
  switch (propertyType.path) {
864
956
  case PRIMITIVE_TYPE.NUMBER:
@@ -874,6 +966,10 @@ export class QueryBuilderExplorerState {
874
966
  this.queryBuilderState.executionContextState.mapping,
875
967
  runtime,
876
968
  this.queryBuilderState.graphManagerState.graph,
969
+ {
970
+ abortController:
971
+ this.previewDataState.previewDataAbortController,
972
+ },
877
973
  )) as ExecutionResult;
878
974
  assertType(
879
975
  previewResult,
@@ -911,6 +1007,10 @@ export class QueryBuilderExplorerState {
911
1007
  this.queryBuilderState.executionContextState.mapping,
912
1008
  runtime,
913
1009
  this.queryBuilderState.graphManagerState.graph,
1010
+ {
1011
+ abortController:
1012
+ this.previewDataState.previewDataAbortController,
1013
+ },
914
1014
  )) as ExecutionResult;
915
1015
  assertType(
916
1016
  previewResult,
@@ -929,12 +1029,16 @@ export class QueryBuilderExplorerState {
929
1029
  }
930
1030
  } catch (error) {
931
1031
  assertErrorThrown(error);
1032
+ if (error.name === 'AbortError') {
1033
+ return;
1034
+ }
932
1035
  this.queryBuilderState.applicationStore.notificationService.notifyWarning(
933
1036
  `Can't preview data for property '${node.property.name}'. Error: ${error.message}`,
934
1037
  );
935
1038
  this.previewDataState.setPreviewData(undefined);
936
1039
  } finally {
937
1040
  this.previewDataState.setIsGeneratingPreviewData(false);
1041
+ this.previewDataState.setPreviewDataAbortController(undefined);
938
1042
  }
939
1043
  }
940
1044
  }