@finos/legend-query-builder 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/QueryBuilder.js +1 -1
- package/lib/components/QueryBuilder.js.map +1 -1
- package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
- package/lib/components/QueryBuilderResultPanel.js +15 -5
- package/lib/components/QueryBuilderResultPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +19 -17
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js +34 -31
- package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +3 -3
- package/lib/stores/QueryBuilderResultState.d.ts +7 -3
- package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
- package/lib/stores/QueryBuilderResultState.js +14 -20
- package/lib/stores/QueryBuilderResultState.js.map +1 -1
- package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.d.ts +3 -0
- package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.d.ts.map +1 -1
- package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.js.map +1 -1
- package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts +10 -1
- package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts.map +1 -1
- package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js +36 -1
- package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js.map +1 -1
- package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts +6 -0
- package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts.map +1 -1
- package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js +21 -2
- package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js.map +1 -1
- package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowState.d.ts +1 -0
- package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowState.d.ts.map +1 -1
- package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowState.js +10 -1
- package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowState.js.map +1 -1
- package/package.json +10 -10
- package/src/components/QueryBuilder.tsx +1 -1
- package/src/components/QueryBuilderResultPanel.tsx +30 -17
- package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +128 -126
- package/src/components/fetch-structure/QueryBuilderTDSWindowPanel.tsx +262 -256
- package/src/stores/QueryBuilderResultState.ts +28 -33
- package/src/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.ts +5 -0
- package/src/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.ts +44 -0
- package/src/stores/fetch-structure/tds/QueryBuilderTDSState.ts +28 -0
- package/src/stores/fetch-structure/tds/window/QueryBuilderWindowState.ts +14 -1
@@ -20,26 +20,26 @@ import {
|
|
20
20
|
assertErrorThrown,
|
21
21
|
LogEvent,
|
22
22
|
guaranteeNonNullable,
|
23
|
-
ContentType,
|
24
|
-
guaranteeType,
|
23
|
+
type ContentType,
|
25
24
|
downloadFileUsingDataURI,
|
26
|
-
UnsupportedOperationError,
|
27
25
|
ActionState,
|
28
26
|
StopWatch,
|
27
|
+
getContentTypeFileExtension,
|
29
28
|
} from '@finos/legend-shared';
|
30
29
|
import type { QueryBuilderState } from './QueryBuilderState.js';
|
31
30
|
import {
|
32
31
|
type RawExecutionPlan,
|
33
32
|
type ExecutionResult,
|
34
33
|
type RawLambda,
|
34
|
+
type EXECUTION_SERIALIZATION_FORMAT,
|
35
35
|
GRAPH_MANAGER_EVENT,
|
36
|
-
EXECUTION_SERIALIZATION_FORMAT,
|
37
36
|
RawExecutionResult,
|
38
37
|
buildRawLambdaFromLambdaFunction,
|
39
38
|
reportGraphAnalytics,
|
39
|
+
extractExecutionResultValues,
|
40
40
|
} from '@finos/legend-graph';
|
41
41
|
import { buildLambdaFunction } from './QueryBuilderValueSpecificationBuilder.js';
|
42
|
-
import { ExecutionPlanState } from '@finos/legend-application';
|
42
|
+
import { ExecutionPlanState, TAB_SIZE } from '@finos/legend-application';
|
43
43
|
import {
|
44
44
|
buildExecutionParameterValues,
|
45
45
|
getExecutionQueryFromRawLambda,
|
@@ -50,6 +50,11 @@ import { QUERY_BUILDER_EVENT } from '../application/QueryBuilderEvent.js';
|
|
50
50
|
|
51
51
|
const DEFAULT_LIMIT = 1000;
|
52
52
|
|
53
|
+
export interface ExportDataInfo {
|
54
|
+
contentType: ContentType;
|
55
|
+
serializationFormat?: EXECUTION_SERIALIZATION_FORMAT | undefined;
|
56
|
+
}
|
57
|
+
|
53
58
|
export class QueryBuilderResultState {
|
54
59
|
readonly queryBuilderState: QueryBuilderState;
|
55
60
|
readonly exportDataState = ActionState.create();
|
@@ -148,25 +153,21 @@ export class QueryBuilderResultState {
|
|
148
153
|
return query;
|
149
154
|
}
|
150
155
|
|
151
|
-
*exportData(
|
152
|
-
serializationFormat: EXECUTION_SERIALIZATION_FORMAT,
|
153
|
-
): GeneratorFn<void> {
|
156
|
+
*exportData(format: string): GeneratorFn<void> {
|
154
157
|
try {
|
158
|
+
const exportData =
|
159
|
+
this.queryBuilderState.fetchStructureState.implementation.getExportDataInfo(
|
160
|
+
format,
|
161
|
+
);
|
162
|
+
const contentType = exportData.contentType;
|
163
|
+
const serializationFormat = exportData.serializationFormat;
|
155
164
|
this.exportDataState.inProgress();
|
156
|
-
const mapping = guaranteeNonNullable(
|
157
|
-
this.queryBuilderState.mapping,
|
158
|
-
'Mapping is required to execute query',
|
159
|
-
);
|
160
|
-
const runtime = guaranteeNonNullable(
|
161
|
-
this.queryBuilderState.runtimeValue,
|
162
|
-
`Runtime is required to execute query`,
|
163
|
-
);
|
164
165
|
const query = this.buildExecutionRawLambda();
|
165
166
|
const result =
|
166
167
|
(yield this.queryBuilderState.graphManagerState.graphManager.runQuery(
|
167
168
|
query,
|
168
|
-
mapping,
|
169
|
-
|
169
|
+
this.queryBuilderState.mapping,
|
170
|
+
this.queryBuilderState.runtimeValue,
|
170
171
|
this.queryBuilderState.graphManagerState.graph,
|
171
172
|
{
|
172
173
|
serializationFormat,
|
@@ -176,23 +177,17 @@ export class QueryBuilderResultState {
|
|
176
177
|
),
|
177
178
|
},
|
178
179
|
)) as ExecutionResult;
|
179
|
-
let contentType: ContentType;
|
180
|
-
let fileName = 'result';
|
181
180
|
let content: string;
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
break;
|
191
|
-
default:
|
192
|
-
throw new UnsupportedOperationError(
|
193
|
-
`Can't download file for serialization type: '${serializationFormat}'`,
|
194
|
-
);
|
181
|
+
if (result instanceof RawExecutionResult) {
|
182
|
+
content = result.value;
|
183
|
+
} else {
|
184
|
+
content = JSON.stringify(
|
185
|
+
extractExecutionResultValues(result),
|
186
|
+
null,
|
187
|
+
TAB_SIZE,
|
188
|
+
);
|
195
189
|
}
|
190
|
+
const fileName = `result.${getContentTypeFileExtension(contentType)}`;
|
196
191
|
downloadFileUsingDataURI(fileName, content, contentType);
|
197
192
|
this.exportDataState.pass();
|
198
193
|
} catch (error) {
|
@@ -26,6 +26,7 @@ import type { QueryBuilderExplorerTreePropertyNodeData } from '../explorer/Query
|
|
26
26
|
import type { QueryBuilderState } from '../QueryBuilderState.js';
|
27
27
|
import type { LambdaFunctionBuilderOption } from '../QueryBuilderValueSpecificationBuilderHelper.js';
|
28
28
|
import type { QueryBuilderFetchStructureState } from './QueryBuilderFetchStructureState.js';
|
29
|
+
import type { ExportDataInfo } from '../QueryBuilderResultState.js';
|
29
30
|
|
30
31
|
export enum FETCH_STRUCTURE_IMPLEMENTATION {
|
31
32
|
TABULAR_DATA_STRUCTURE = 'TABULAR_DATA_STRUCTURE',
|
@@ -75,4 +76,8 @@ export abstract class QueryBuilderFetchStructureImplementationState
|
|
75
76
|
get TEMPORARY__showPostFetchStructurePanel(): boolean {
|
76
77
|
return this.queryBuilderState.filterState.showPanel;
|
77
78
|
}
|
79
|
+
|
80
|
+
// export options
|
81
|
+
abstract get exportDataFormatOptions(): string[];
|
82
|
+
abstract getExportDataInfo(format: string): ExportDataInfo;
|
78
83
|
}
|
@@ -51,15 +51,22 @@ import {
|
|
51
51
|
guaranteeNonNullable,
|
52
52
|
hashArray,
|
53
53
|
type Hashable,
|
54
|
+
UnsupportedOperationError,
|
55
|
+
ContentType,
|
54
56
|
} from '@finos/legend-shared';
|
55
57
|
import { QUERY_BUILDER_HASH_STRUCTURE } from '../../../graphManager/QueryBuilderHashUtils.js';
|
56
58
|
import { isValueExpressionReferencedInValue } from '../../QueryBuilderValueSpecificationHelper.js';
|
59
|
+
import type { ExportDataInfo } from '../../QueryBuilderResultState.js';
|
57
60
|
|
58
61
|
export enum SERIALIZATION_TYPE {
|
59
62
|
PURE = 'PURE',
|
60
63
|
EXTERNAL_FORMAT = 'EXTERNAL_FORMAT',
|
61
64
|
}
|
62
65
|
|
66
|
+
export enum GRAPH_FETCH_EXPORT_DATA_FORMAT {
|
67
|
+
RESULT = 'RESULT',
|
68
|
+
}
|
69
|
+
|
63
70
|
const DEFAULT_PURE_CONFIG_TYPE_NAME = '@type';
|
64
71
|
|
65
72
|
export class PureSerializationConfig {
|
@@ -135,6 +142,8 @@ export abstract class GraphFetchSerializationState {
|
|
135
142
|
}
|
136
143
|
|
137
144
|
abstract getLabel(): string;
|
145
|
+
|
146
|
+
abstract get serializationContentType(): ContentType;
|
138
147
|
}
|
139
148
|
|
140
149
|
export class GraphFetchPureSerializationState extends GraphFetchSerializationState {
|
@@ -161,6 +170,10 @@ export class GraphFetchPureSerializationState extends GraphFetchSerializationSta
|
|
161
170
|
override getLabel(): string {
|
162
171
|
return SERIALIZATION_TYPE.PURE;
|
163
172
|
}
|
173
|
+
|
174
|
+
override get serializationContentType(): ContentType {
|
175
|
+
return ContentType.APPLICATION_JSON;
|
176
|
+
}
|
164
177
|
}
|
165
178
|
|
166
179
|
export class GraphFetchExternalFormatSerializationState extends GraphFetchSerializationState {
|
@@ -176,6 +189,7 @@ export class GraphFetchExternalFormatSerializationState extends GraphFetchSerial
|
|
176
189
|
makeObservable(this, {
|
177
190
|
targetBinding: observable,
|
178
191
|
treeData: observable.ref,
|
192
|
+
serializationContentType: computed,
|
179
193
|
});
|
180
194
|
this.targetBinding = targetBinding;
|
181
195
|
this.treeData = treeData;
|
@@ -192,6 +206,20 @@ export class GraphFetchExternalFormatSerializationState extends GraphFetchSerial
|
|
192
206
|
override getLabel(): string {
|
193
207
|
return SERIALIZATION_TYPE.EXTERNAL_FORMAT;
|
194
208
|
}
|
209
|
+
|
210
|
+
override get serializationContentType(): ContentType {
|
211
|
+
const contentType = this.targetBinding.contentType;
|
212
|
+
if (Object.values(ContentType).includes(contentType as ContentType)) {
|
213
|
+
return contentType as ContentType;
|
214
|
+
} else {
|
215
|
+
// TEMP: need to investigate if flatdata should be returned as content type
|
216
|
+
// for now we will assume all flatdata is csv
|
217
|
+
if (contentType === 'application/x.flatdata') {
|
218
|
+
return ContentType.TEXT_CSV;
|
219
|
+
}
|
220
|
+
return ContentType.TEXT_PLAIN;
|
221
|
+
}
|
222
|
+
}
|
195
223
|
}
|
196
224
|
|
197
225
|
export class QueryBuilderGraphFetchTreeState
|
@@ -321,6 +349,22 @@ export class QueryBuilderGraphFetchTreeState
|
|
321
349
|
);
|
322
350
|
}
|
323
351
|
|
352
|
+
override get exportDataFormatOptions(): string[] {
|
353
|
+
return [GRAPH_FETCH_EXPORT_DATA_FORMAT.RESULT];
|
354
|
+
}
|
355
|
+
|
356
|
+
override getExportDataInfo(format: string): ExportDataInfo {
|
357
|
+
if (format === GRAPH_FETCH_EXPORT_DATA_FORMAT.RESULT) {
|
358
|
+
return {
|
359
|
+
contentType: this.serializationState.serializationContentType,
|
360
|
+
};
|
361
|
+
} else {
|
362
|
+
throw new UnsupportedOperationError(
|
363
|
+
`Unsupported Graph Fetch export type ${format}`,
|
364
|
+
);
|
365
|
+
}
|
366
|
+
}
|
367
|
+
|
324
368
|
onClassChange(_class: Class | undefined): void {
|
325
369
|
this.updateTreeData(_class);
|
326
370
|
}
|
@@ -35,6 +35,8 @@ import {
|
|
35
35
|
filterByType,
|
36
36
|
type Hashable,
|
37
37
|
hashArray,
|
38
|
+
UnsupportedOperationError,
|
39
|
+
ContentType,
|
38
40
|
} from '@finos/legend-shared';
|
39
41
|
import type { QueryBuilderState } from '../../QueryBuilderState.js';
|
40
42
|
import {
|
@@ -52,6 +54,7 @@ import {
|
|
52
54
|
matchFunctionName,
|
53
55
|
SimpleFunctionExpression,
|
54
56
|
getAllSuperclasses,
|
57
|
+
EXECUTION_SERIALIZATION_FORMAT,
|
55
58
|
} from '@finos/legend-graph';
|
56
59
|
import {
|
57
60
|
DEFAULT_LAMBDA_VARIABLE_NAME,
|
@@ -97,6 +100,12 @@ import type { QueryBuilderTDS_WindowOperator } from './window/operators/QueryBui
|
|
97
100
|
import { getQueryBuilderCoreWindowOperators } from './window/QueryBuilderWindowGroupByOperatorLoader.js';
|
98
101
|
import type { QueryBuilderTDSColumnState } from './QueryBuilderTDSColumnState.js';
|
99
102
|
import { QUERY_BUILDER_SETTING_KEY } from '../../../application/QueryBuilderSetting.js';
|
103
|
+
import type { ExportDataInfo } from '../../QueryBuilderResultState.js';
|
104
|
+
|
105
|
+
// TODO: should we support raw once externalize() is supported on TDS ?
|
106
|
+
export enum TDS_EXECUTION_SERIALIZATION_FORMAT {
|
107
|
+
CSV = 'CSV',
|
108
|
+
}
|
100
109
|
|
101
110
|
export class QueryBuilderTDSState
|
102
111
|
extends QueryBuilderFetchStructureImplementationState
|
@@ -289,6 +298,25 @@ export class QueryBuilderTDSState
|
|
289
298
|
];
|
290
299
|
}
|
291
300
|
|
301
|
+
override get exportDataFormatOptions(): string[] {
|
302
|
+
return [TDS_EXECUTION_SERIALIZATION_FORMAT.CSV];
|
303
|
+
}
|
304
|
+
|
305
|
+
override getExportDataInfo(format: string): ExportDataInfo {
|
306
|
+
switch (format) {
|
307
|
+
case TDS_EXECUTION_SERIALIZATION_FORMAT.CSV:
|
308
|
+
return {
|
309
|
+
contentType: ContentType.TEXT_CSV,
|
310
|
+
serializationFormat: EXECUTION_SERIALIZATION_FORMAT.CSV,
|
311
|
+
};
|
312
|
+
|
313
|
+
default:
|
314
|
+
throw new UnsupportedOperationError(
|
315
|
+
`Unsupported TDS export type ${format}`,
|
316
|
+
);
|
317
|
+
}
|
318
|
+
}
|
319
|
+
|
292
320
|
isDuplicateColumn(col: QueryBuilderTDSColumnState): boolean {
|
293
321
|
return (
|
294
322
|
this.tdsColumns.filter((c) => c.columnName === col.columnName).length > 1
|
@@ -23,7 +23,7 @@ import {
|
|
23
23
|
uniq,
|
24
24
|
type Hashable,
|
25
25
|
} from '@finos/legend-shared';
|
26
|
-
import { action, makeObservable, observable } from 'mobx';
|
26
|
+
import { action, computed, makeObservable, observable } from 'mobx';
|
27
27
|
import { QUERY_BUILDER_HASH_STRUCTURE } from '../../../../graphManager/QueryBuilderHashUtils.js';
|
28
28
|
import { DEFAULT_LAMBDA_VARIABLE_NAME } from '../../../QueryBuilderConfig.js';
|
29
29
|
import type { QueryBuilderProjectionColumnDragSource } from '../projection/QueryBuilderProjectionColumnState.js';
|
@@ -333,6 +333,7 @@ export class QueryBuilderWindowState implements Hashable {
|
|
333
333
|
makeObservable(this, {
|
334
334
|
windowColumns: observable,
|
335
335
|
editColumn: observable,
|
336
|
+
validationIssues: computed,
|
336
337
|
addWindowColumn: action,
|
337
338
|
removeColumn: action,
|
338
339
|
moveColumn: action,
|
@@ -346,6 +347,18 @@ export class QueryBuilderWindowState implements Hashable {
|
|
346
347
|
return !this.windowColumns.length;
|
347
348
|
}
|
348
349
|
|
350
|
+
get validationIssues(): string[] | undefined {
|
351
|
+
const hasDuplicatedWindowColumns = this.windowColumns.some(
|
352
|
+
(column) =>
|
353
|
+
this.windowColumns.filter((c) => c.columnName === column.columnName)
|
354
|
+
.length > 1,
|
355
|
+
);
|
356
|
+
if (hasDuplicatedWindowColumns) {
|
357
|
+
return ['Query has duplicated window columns'];
|
358
|
+
}
|
359
|
+
return undefined;
|
360
|
+
}
|
361
|
+
|
349
362
|
get referencedTDSColumns(): QueryBuilderTDSColumnState[] {
|
350
363
|
return uniq(this.windowColumns.map((c) => c.referencedTDSColumns).flat());
|
351
364
|
}
|