@finos/legend-data-cube 0.0.35 → 0.0.37
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/README.md +1 -1
- package/lib/__lib__/DataCubeEvent.d.ts +21 -0
- package/lib/__lib__/DataCubeEvent.d.ts.map +1 -0
- package/lib/__lib__/DataCubeEvent.js +22 -0
- package/lib/__lib__/DataCubeEvent.js.map +1 -0
- package/lib/components/DataCube.d.ts +3 -1
- package/lib/components/DataCube.d.ts.map +1 -1
- package/lib/components/DataCube.js +10 -9
- package/lib/components/DataCube.js.map +1 -1
- package/lib/components/DataCubeProvider.js +1 -1
- package/lib/components/DataCubeProvider.js.map +1 -1
- package/lib/components/core/DataCubeAlert.d.ts +3 -2
- package/lib/components/core/DataCubeAlert.d.ts.map +1 -1
- package/lib/components/core/DataCubeAlert.js +4 -2
- package/lib/components/core/DataCubeAlert.js.map +1 -1
- package/lib/components/core/DataCubeFormUtils.d.ts +26 -0
- package/lib/components/core/DataCubeFormUtils.d.ts.map +1 -1
- package/lib/components/core/DataCubeFormUtils.js +127 -4
- package/lib/components/core/DataCubeFormUtils.js.map +1 -1
- package/lib/components/core/DataCubeLayoutManager.js +1 -1
- package/lib/components/core/DataCubeLayoutManager.js.map +1 -1
- package/lib/components/core/DataCubeSettingsPanel.d.ts.map +1 -1
- package/lib/components/core/DataCubeSettingsPanel.js +53 -27
- package/lib/components/core/DataCubeSettingsPanel.js.map +1 -1
- package/lib/components/view/editor/DataCubeEditor.d.ts.map +1 -1
- package/lib/components/view/editor/DataCubeEditor.js +6 -5
- package/lib/components/view/editor/DataCubeEditor.js.map +1 -1
- package/lib/components/view/editor/DataCubeEditorColumnPropertiesPanel.d.ts.map +1 -1
- package/lib/components/view/editor/DataCubeEditorColumnPropertiesPanel.js +4 -4
- package/lib/components/view/editor/DataCubeEditorColumnPropertiesPanel.js.map +1 -1
- package/lib/components/view/editor/DataCubeEditorGeneralPropertiesPanel.d.ts.map +1 -1
- package/lib/components/view/editor/DataCubeEditorGeneralPropertiesPanel.js +2 -2
- package/lib/components/view/editor/DataCubeEditorGeneralPropertiesPanel.js.map +1 -1
- package/lib/components/view/extend/DataCubeColumnEditor.d.ts.map +1 -1
- package/lib/components/view/extend/DataCubeColumnEditor.js +12 -12
- package/lib/components/view/extend/DataCubeColumnEditor.js.map +1 -1
- package/lib/components/view/filter/DataCubeFilterEditor.d.ts.map +1 -1
- package/lib/components/view/filter/DataCubeFilterEditor.js +4 -4
- package/lib/components/view/filter/DataCubeFilterEditor.js.map +1 -1
- package/lib/components/view/grid/DataCubeGrid.d.ts.map +1 -1
- package/lib/components/view/grid/DataCubeGrid.js +7 -7
- package/lib/components/view/grid/DataCubeGrid.js.map +1 -1
- package/lib/index.css +1 -1
- package/lib/index.d.ts +7 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +7 -2
- package/lib/index.js.map +1 -1
- package/lib/package.json +2 -2
- package/lib/stores/DataCubeOptions.d.ts +6 -5
- package/lib/stores/DataCubeOptions.d.ts.map +1 -1
- package/lib/stores/DataCubeSettings.d.ts +25 -22
- package/lib/stores/DataCubeSettings.d.ts.map +1 -1
- package/lib/stores/DataCubeSettings.js +250 -62
- package/lib/stores/DataCubeSettings.js.map +1 -1
- package/lib/stores/DataCubeState.d.ts +8 -5
- package/lib/stores/DataCubeState.d.ts.map +1 -1
- package/lib/stores/DataCubeState.js +27 -42
- package/lib/stores/DataCubeState.js.map +1 -1
- package/lib/stores/core/DataCubeEngine.d.ts +15 -18
- package/lib/stores/core/DataCubeEngine.d.ts.map +1 -1
- package/lib/stores/core/DataCubeEngine.js +5 -16
- package/lib/stores/core/DataCubeEngine.js.map +1 -1
- package/lib/stores/core/DataCubeQueryBuilder.d.ts +1 -0
- package/lib/stores/core/DataCubeQueryBuilder.d.ts.map +1 -1
- package/lib/stores/core/DataCubeQueryBuilder.js.map +1 -1
- package/lib/stores/core/DataCubeQueryBuilderUtils.d.ts +3 -0
- package/lib/stores/core/DataCubeQueryBuilderUtils.d.ts.map +1 -1
- package/lib/stores/core/DataCubeQueryBuilderUtils.js +12 -1
- package/lib/stores/core/DataCubeQueryBuilderUtils.js.map +1 -1
- package/lib/stores/core/DataCubeQuerySnapshotBuilder.d.ts.map +1 -1
- package/lib/stores/core/DataCubeQuerySnapshotBuilder.js +46 -30
- package/lib/stores/core/DataCubeQuerySnapshotBuilder.js.map +1 -1
- package/lib/stores/core/DataCubeSetting.d.ts +51 -0
- package/lib/stores/core/DataCubeSetting.d.ts.map +1 -0
- package/lib/stores/core/DataCubeSetting.js +36 -0
- package/lib/stores/core/DataCubeSetting.js.map +1 -0
- package/lib/stores/core/models/AdhocQueryDataCubeSource.d.ts +29 -0
- package/lib/stores/core/models/AdhocQueryDataCubeSource.d.ts.map +1 -0
- package/lib/stores/core/models/AdhocQueryDataCubeSource.js +35 -0
- package/lib/stores/core/models/AdhocQueryDataCubeSource.js.map +1 -0
- package/lib/stores/core/models/DataCubeSource.d.ts +1 -1
- package/lib/stores/core/models/DataCubeSource.d.ts.map +1 -1
- package/lib/stores/core/models/DataCubeSource.js +1 -1
- package/lib/stores/core/models/DataCubeSource.js.map +1 -1
- package/lib/stores/view/DataCubeQuerySnapshotManager.d.ts.map +1 -1
- package/lib/stores/view/DataCubeQuerySnapshotManager.js +9 -2
- package/lib/stores/view/DataCubeQuerySnapshotManager.js.map +1 -1
- package/lib/stores/view/DataCubeViewState.d.ts +1 -1
- package/lib/stores/view/DataCubeViewState.d.ts.map +1 -1
- package/lib/stores/view/DataCubeViewState.js +5 -14
- package/lib/stores/view/DataCubeViewState.js.map +1 -1
- package/lib/stores/view/extend/DataCubeColumnEditorState.d.ts.map +1 -1
- package/lib/stores/view/extend/DataCubeColumnEditorState.js +5 -5
- package/lib/stores/view/extend/DataCubeColumnEditorState.js.map +1 -1
- package/lib/stores/view/grid/DataCubeGridClientEngine.d.ts +1 -1
- package/lib/stores/view/grid/DataCubeGridClientEngine.d.ts.map +1 -1
- package/lib/stores/view/grid/DataCubeGridClientEngine.js +11 -7
- package/lib/stores/view/grid/DataCubeGridClientEngine.js.map +1 -1
- package/lib/stores/view/grid/DataCubeGridQueryBuilder.d.ts.map +1 -1
- package/lib/stores/view/grid/DataCubeGridQueryBuilder.js +2 -2
- package/lib/stores/view/grid/DataCubeGridQueryBuilder.js.map +1 -1
- package/lib/stores/view/grid/DataCubeGridState.d.ts +1 -0
- package/lib/stores/view/grid/DataCubeGridState.d.ts.map +1 -1
- package/lib/stores/view/grid/DataCubeGridState.js +8 -3
- package/lib/stores/view/grid/DataCubeGridState.js.map +1 -1
- package/package.json +6 -6
- package/src/__lib__/DataCubeEvent.ts +21 -0
- package/src/components/DataCube.tsx +14 -8
- package/src/components/DataCubeProvider.tsx +1 -1
- package/src/components/core/DataCubeAlert.tsx +12 -7
- package/src/components/core/DataCubeFormUtils.tsx +245 -16
- package/src/components/core/DataCubeLayoutManager.tsx +1 -1
- package/src/components/core/DataCubeSettingsPanel.tsx +166 -134
- package/src/components/view/editor/DataCubeEditor.tsx +12 -16
- package/src/components/view/editor/DataCubeEditorColumnPropertiesPanel.tsx +6 -5
- package/src/components/view/editor/DataCubeEditorGeneralPropertiesPanel.tsx +4 -3
- package/src/components/view/extend/DataCubeColumnEditor.tsx +24 -28
- package/src/components/view/filter/DataCubeFilterEditor.tsx +10 -18
- package/src/components/view/grid/DataCubeGrid.tsx +8 -7
- package/src/index.tsx +13 -2
- package/src/stores/DataCubeOptions.ts +14 -10
- package/src/stores/DataCubeSettings.tsx +421 -0
- package/src/stores/DataCubeState.tsx +38 -51
- package/src/stores/core/DataCubeEngine.tsx +45 -62
- package/src/stores/core/DataCubeQueryBuilder.ts +1 -0
- package/src/stores/core/DataCubeQueryBuilderUtils.ts +17 -0
- package/src/stores/core/DataCubeQuerySnapshotBuilder.ts +59 -30
- package/src/stores/core/DataCubeSetting.ts +63 -0
- package/src/stores/core/models/AdhocQueryDataCubeSource.ts +45 -0
- package/src/stores/core/models/DataCubeSource.ts +1 -1
- package/src/stores/view/DataCubeQuerySnapshotManager.ts +16 -4
- package/src/stores/view/DataCubeViewState.ts +8 -17
- package/src/stores/view/extend/DataCubeColumnEditorState.tsx +8 -6
- package/src/stores/view/grid/DataCubeGridClientEngine.ts +22 -11
- package/src/stores/view/grid/DataCubeGridQueryBuilder.ts +7 -1
- package/src/stores/view/grid/DataCubeGridState.ts +17 -3
- package/tsconfig.json +4 -1
- package/src/stores/DataCubeSettings.ts +0 -107
|
@@ -69,22 +69,16 @@ import {
|
|
|
69
69
|
configureCodeEditor,
|
|
70
70
|
setupPureLanguageService,
|
|
71
71
|
} from '@finos/legend-code-editor';
|
|
72
|
-
import { DataCubeFont
|
|
72
|
+
import { DataCubeFont } from './DataCubeQueryEngine.js';
|
|
73
73
|
import type { DataCubeQuerySnapshot } from './DataCubeQuerySnapshot.js';
|
|
74
74
|
import { buildExecutableQuery } from './DataCubeQueryBuilder.js';
|
|
75
75
|
import type { DataCubeColumn } from './models/DataCubeColumn.js';
|
|
76
76
|
import { LicenseManager } from 'ag-grid-enterprise';
|
|
77
|
-
import type { DataCubeQuery } from './models/DataCubeQuery.js';
|
|
78
77
|
import {
|
|
79
78
|
type DataCubeSource,
|
|
80
79
|
INTERNAL__DataCubeSource,
|
|
81
80
|
} from './models/DataCubeSource.js';
|
|
82
|
-
import {
|
|
83
|
-
_cols,
|
|
84
|
-
_colSpec,
|
|
85
|
-
_function,
|
|
86
|
-
_primitiveValue,
|
|
87
|
-
} from './DataCubeQueryBuilderUtils.js';
|
|
81
|
+
import { _primitiveValue } from './DataCubeQueryBuilderUtils.js';
|
|
88
82
|
import {
|
|
89
83
|
uuid,
|
|
90
84
|
type DocumentationEntry,
|
|
@@ -105,27 +99,26 @@ import {
|
|
|
105
99
|
} from './DataCubeLayoutManagerState.js';
|
|
106
100
|
import { editor as monacoEditorAPI, Uri } from 'monaco-editor';
|
|
107
101
|
import { DataCubeCodeCheckErrorAlert } from '../../components/core/DataCubeCodeCheckErrorAlert.js';
|
|
108
|
-
import type { DataCubeAPI } from '../DataCubeAPI.js';
|
|
109
102
|
|
|
110
103
|
export type CompletionItem = {
|
|
111
104
|
completion: string;
|
|
112
105
|
display: string;
|
|
113
106
|
};
|
|
114
107
|
|
|
115
|
-
export type
|
|
108
|
+
export type DataCubeRelationType = {
|
|
116
109
|
columns: DataCubeColumn[];
|
|
117
110
|
};
|
|
118
111
|
|
|
112
|
+
export type DataCubeExecutionOptions = {
|
|
113
|
+
debug?: boolean | undefined;
|
|
114
|
+
};
|
|
115
|
+
|
|
119
116
|
export type DataCubeExecutionResult = {
|
|
120
117
|
result: TDSExecutionResult;
|
|
121
118
|
executedQuery: string;
|
|
122
119
|
executedSQL: string;
|
|
123
120
|
};
|
|
124
121
|
|
|
125
|
-
export type DataCubeEngineConfiguration = {
|
|
126
|
-
gridClientLicense?: string | undefined;
|
|
127
|
-
};
|
|
128
|
-
|
|
129
122
|
export abstract class DataCubeEngine {
|
|
130
123
|
readonly layout = new LayoutManagerState();
|
|
131
124
|
readonly filterOperations = [
|
|
@@ -176,16 +169,11 @@ export abstract class DataCubeEngine {
|
|
|
176
169
|
new DataCubeQueryAggregateOperation__JoinStrings(),
|
|
177
170
|
];
|
|
178
171
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
async initialize(): Promise<void> {
|
|
186
|
-
const config = await this.fetchConfiguration();
|
|
187
|
-
if (config.gridClientLicense) {
|
|
188
|
-
LicenseManager.setLicenseKey(config.gridClientLicense);
|
|
172
|
+
async initialize(options?: {
|
|
173
|
+
gridClientLicense?: string | undefined;
|
|
174
|
+
}): Promise<void> {
|
|
175
|
+
if (options?.gridClientLicense) {
|
|
176
|
+
LicenseManager.setLicenseKey(options.gridClientLicense);
|
|
189
177
|
}
|
|
190
178
|
await configureCodeEditor(DataCubeFont.ROBOTO_MONO, (error) => {
|
|
191
179
|
throw error;
|
|
@@ -203,7 +191,36 @@ export abstract class DataCubeEngine {
|
|
|
203
191
|
return getAggregateOperation(value, this.aggregateOperations);
|
|
204
192
|
}
|
|
205
193
|
|
|
206
|
-
|
|
194
|
+
/**
|
|
195
|
+
* By default, for a function chain, Pure grammar composer will extract the first parameter of the first function
|
|
196
|
+
* and render it as the caller of that function rather than a parameter
|
|
197
|
+
* e.g. fx(fy(p1, p2), p3) will be rendered as p1->fy(p2)->fx(p3) instead of fy(p1, p2)-> fx(p3)
|
|
198
|
+
*
|
|
199
|
+
* We do a hack to get around this by setting a dummy value as the first parameter of the first function in the chain.
|
|
200
|
+
* Then remove this dummy value from the final code.
|
|
201
|
+
*/
|
|
202
|
+
async getPartialQueryCode(
|
|
203
|
+
snapshot: DataCubeQuerySnapshot,
|
|
204
|
+
pretty?: boolean | undefined,
|
|
205
|
+
) {
|
|
206
|
+
const source = new INTERNAL__DataCubeSource();
|
|
207
|
+
source.query = _primitiveValue(PRIMITIVE_TYPE.STRING, '');
|
|
208
|
+
return (
|
|
209
|
+
await this.getValueSpecificationCode(
|
|
210
|
+
buildExecutableQuery(
|
|
211
|
+
snapshot,
|
|
212
|
+
source,
|
|
213
|
+
() => undefined,
|
|
214
|
+
this.filterOperations,
|
|
215
|
+
this.aggregateOperations,
|
|
216
|
+
),
|
|
217
|
+
pretty,
|
|
218
|
+
)
|
|
219
|
+
).substring(`''->`.length);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// ---------------------------------- INTERFACE ----------------------------------
|
|
223
|
+
|
|
207
224
|
abstract processQuerySource(value: PlainObject): Promise<DataCubeSource>;
|
|
208
225
|
|
|
209
226
|
abstract parseValueSpecification(
|
|
@@ -225,58 +242,24 @@ export abstract class DataCubeEngine {
|
|
|
225
242
|
abstract getQueryRelationType(
|
|
226
243
|
query: V1_Lambda,
|
|
227
244
|
source: DataCubeSource,
|
|
228
|
-
): Promise<
|
|
245
|
+
): Promise<DataCubeRelationType>;
|
|
229
246
|
|
|
230
247
|
abstract getQueryCodeRelationReturnType(
|
|
231
248
|
code: string,
|
|
232
249
|
baseQuery: V1_ValueSpecification,
|
|
233
250
|
source: DataCubeSource,
|
|
234
|
-
): Promise<
|
|
251
|
+
): Promise<DataCubeRelationType>;
|
|
235
252
|
|
|
236
253
|
abstract executeQuery(
|
|
237
254
|
query: V1_Lambda,
|
|
238
255
|
source: DataCubeSource,
|
|
239
|
-
|
|
256
|
+
options?: DataCubeExecutionOptions | undefined,
|
|
240
257
|
): Promise<DataCubeExecutionResult>;
|
|
241
258
|
|
|
242
259
|
abstract buildExecutionContext(
|
|
243
260
|
source: DataCubeSource,
|
|
244
261
|
): V1_AppliedFunction | undefined;
|
|
245
262
|
|
|
246
|
-
/**
|
|
247
|
-
* By default, for a function chain, Pure grammar composer will extract the first parameter of the first function
|
|
248
|
-
* and render it as the caller of that function rather than a parameter
|
|
249
|
-
* e.g. fx(fy(p1, p2), p3) will be rendered as p1->fy(p2)->fx(p3) instead of fy(p1, p2)-> fx(p3)
|
|
250
|
-
*
|
|
251
|
-
* We do a hack to get around this by setting a dummy value as the first parameter of the first function in the chain.
|
|
252
|
-
* Then remove this dummy value from the final code.
|
|
253
|
-
*/
|
|
254
|
-
async getPartialQueryCode(
|
|
255
|
-
snapshot: DataCubeQuerySnapshot,
|
|
256
|
-
pretty?: boolean | undefined,
|
|
257
|
-
) {
|
|
258
|
-
const source = new INTERNAL__DataCubeSource();
|
|
259
|
-
source.query = _primitiveValue(PRIMITIVE_TYPE.STRING, '');
|
|
260
|
-
return (
|
|
261
|
-
await this.getValueSpecificationCode(
|
|
262
|
-
buildExecutableQuery(
|
|
263
|
-
snapshot,
|
|
264
|
-
source,
|
|
265
|
-
() => undefined,
|
|
266
|
-
this.filterOperations,
|
|
267
|
-
this.aggregateOperations,
|
|
268
|
-
),
|
|
269
|
-
pretty,
|
|
270
|
-
)
|
|
271
|
-
).substring(`''->`.length);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
generateInitialQuery(snapshot: DataCubeQuerySnapshot): V1_AppliedFunction {
|
|
275
|
-
return _function(DataCubeFunction.SELECT, [
|
|
276
|
-
_cols(snapshot.data.sourceColumns.map((col) => _colSpec(col.name))),
|
|
277
|
-
]);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
263
|
// ---------------------------------- DOCUMENTATION ----------------------------------
|
|
281
264
|
|
|
282
265
|
getDocumentationURL(): string | undefined {
|
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
V1_createGenericTypeWithRawType,
|
|
54
54
|
V1_createRelationType,
|
|
55
55
|
V1_createRelationTypeColumn,
|
|
56
|
+
V1_serializeValueSpecification,
|
|
56
57
|
} from '@finos/legend-graph';
|
|
57
58
|
import {
|
|
58
59
|
type DataCubeQuerySnapshotFilterCondition,
|
|
@@ -117,6 +118,16 @@ export function _deserializeLambda(json: PlainObject<V1_Lambda>) {
|
|
|
117
118
|
return guaranteeType(V1_deserializeValueSpecification(json, []), V1_Lambda);
|
|
118
119
|
}
|
|
119
120
|
|
|
121
|
+
export function _deserializeValueSpecification(
|
|
122
|
+
json: PlainObject<V1_ValueSpecification>,
|
|
123
|
+
) {
|
|
124
|
+
return V1_deserializeValueSpecification(json, []);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function _serializeValueSpecification(protocol: V1_ValueSpecification) {
|
|
128
|
+
return V1_serializeValueSpecification(protocol, []);
|
|
129
|
+
}
|
|
130
|
+
|
|
120
131
|
export function _deserializeFunction(json: PlainObject<V1_Lambda>) {
|
|
121
132
|
return guaranteeType(
|
|
122
133
|
V1_deserializeValueSpecification(json, []),
|
|
@@ -304,6 +315,12 @@ export function _not(fn: V1_AppliedFunction) {
|
|
|
304
315
|
return _function(_functionName(DataCubeFunction.NOT), [fn]);
|
|
305
316
|
}
|
|
306
317
|
|
|
318
|
+
export function _selectFunction(columns: DataCubeColumn[]) {
|
|
319
|
+
return _function(DataCubeFunction.SELECT, [
|
|
320
|
+
_cols(columns.map((col) => _colSpec(col.name))),
|
|
321
|
+
]);
|
|
322
|
+
}
|
|
323
|
+
|
|
307
324
|
// --------------------------------- BUILDING BLOCKS ---------------------------------
|
|
308
325
|
|
|
309
326
|
export function _col(
|
|
@@ -301,12 +301,12 @@ export function validateAndBuildQuerySnapshot(
|
|
|
301
301
|
return _toCol(column);
|
|
302
302
|
};
|
|
303
303
|
|
|
304
|
-
//
|
|
304
|
+
// -------------------------------- SOURCE --------------------------------
|
|
305
305
|
|
|
306
|
-
data.sourceColumns = source.
|
|
306
|
+
data.sourceColumns = source.columns;
|
|
307
307
|
data.sourceColumns.forEach((col) => colsMap.set(col.name, col));
|
|
308
308
|
|
|
309
|
-
//
|
|
309
|
+
// --------------------------- LEAF-LEVEL EXTEND ---------------------------
|
|
310
310
|
/** TODO: @datacube roundtrip */
|
|
311
311
|
|
|
312
312
|
// --------------------------------- FILTER ---------------------------------
|
|
@@ -336,7 +336,7 @@ export function validateAndBuildQuerySnapshot(
|
|
|
336
336
|
};
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
//
|
|
339
|
+
// --------------------------- GROUP-LEVEL EXTEND ---------------------------
|
|
340
340
|
/** TODO: @datacube roundtrip */
|
|
341
341
|
|
|
342
342
|
// --------------------------------- SORT ---------------------------------
|
|
@@ -368,41 +368,70 @@ export function validateAndBuildQuerySnapshot(
|
|
|
368
368
|
}
|
|
369
369
|
|
|
370
370
|
// --------------------------------- CONFIGURATION ---------------------------------
|
|
371
|
-
// NOTE: we aim to keep the data query a Pure query instead of a specification object
|
|
372
|
-
// so this configuration holds mostly layout and styling customization.
|
|
373
|
-
// But there are overlaps, i.e. certain data query configuration are stored in the
|
|
374
|
-
// configuration, e.g. column aggregation type, this is because a column
|
|
375
|
-
// aggregation's preference can be populated even when there's no aggregation specified
|
|
376
|
-
// in the data query.
|
|
377
371
|
//
|
|
378
|
-
//
|
|
379
|
-
//
|
|
380
|
-
//
|
|
381
|
-
//
|
|
372
|
+
// A data-cube conceptually consists of a data query, in form of a Pure query, instead
|
|
373
|
+
// of a particular specification object format, and this configuration, that holds mostly
|
|
374
|
+
// layout and styling customization. But there are overlaps, i.e. certain "meta" query
|
|
375
|
+
// configuration are stored in this configuration, e.g. column aggregation type, because
|
|
376
|
+
// a column aggregation's preference needs to be specified even when there's no aggregation
|
|
377
|
+
// specified over that column in the data query.
|
|
378
|
+
//
|
|
379
|
+
// But in the example above, if the column is part of an aggregation, we have to ensure
|
|
380
|
+
// the configuration is consistent with the query. Conflicts can happen, for example:
|
|
382
381
|
// - column kind and type conflict with aggregation
|
|
383
382
|
// - column kind and type conflict with the column configuration
|
|
384
383
|
//
|
|
385
|
-
// In
|
|
386
|
-
//
|
|
387
|
-
//
|
|
384
|
+
// In those cases, we need to reconcile to make sure the query and the configuration to agree.
|
|
385
|
+
// The query will take precedence when conflicts happen, and if the conflict cannot be resolved
|
|
386
|
+
// somehow, we will throw a validation error. We decide so because in certain cases, configuration
|
|
387
|
+
// needs to be generated from default presets, such as for use cases where the query comes from a
|
|
388
|
+
// different source, such as Studio or Query, or another part of Engine, where the layout
|
|
389
|
+
// configuration is not specified.
|
|
390
|
+
//
|
|
391
|
+
// ----------------------------------------------------------------------------------
|
|
392
|
+
|
|
393
|
+
const configuration = validateAndBuildConfiguration(
|
|
394
|
+
snapshot,
|
|
395
|
+
funcMap,
|
|
396
|
+
baseQuery,
|
|
397
|
+
);
|
|
398
|
+
data.configuration = configuration.serialize();
|
|
399
|
+
|
|
400
|
+
return snapshot.finalize();
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* TODO: @datacube roundtrip - implement the logic to reconcile the configuration with the query
|
|
405
|
+
* - [ ] disallow naming an extended column the same as a source column/leaf-level extended column
|
|
406
|
+
* even if the column is not selected
|
|
407
|
+
* - [ ] columns (missing/extra columns - remove or generate default column configuration)
|
|
408
|
+
* - [ ] column kind
|
|
409
|
+
* - [ ] column type
|
|
410
|
+
* - [ ] base off the type, check the settings
|
|
411
|
+
* - [ ] aggregation
|
|
412
|
+
* - [ ] verify groupBy agg columns, pivot agg columns and configuration agree
|
|
413
|
+
* - [ ] verify groupBy sort columns and tree column sort direction configuration agree
|
|
414
|
+
*/
|
|
415
|
+
function validateAndBuildConfiguration(
|
|
416
|
+
snapshot: DataCubeQuerySnapshot,
|
|
417
|
+
funcMap: DataCubeQueryFunctionMap,
|
|
418
|
+
baseQuery: DataCubeQuery,
|
|
419
|
+
) {
|
|
420
|
+
const data = snapshot.data;
|
|
388
421
|
const configuration =
|
|
389
422
|
baseQuery.configuration?.clone() ??
|
|
390
423
|
buildDefaultConfiguration([
|
|
391
|
-
...
|
|
424
|
+
...data.sourceColumns,
|
|
392
425
|
...data.leafExtendedColumns,
|
|
393
426
|
...data.groupExtendedColumns,
|
|
394
427
|
]);
|
|
395
|
-
data.configuration = configuration.serialize();
|
|
396
|
-
/**
|
|
397
|
-
* TODO: @datacube roundtrip - implement the logic to reconcile the configuration with the query
|
|
398
|
-
* - [ ] columns (missing/extra columns - remove or generate default column configuration)
|
|
399
|
-
* - [ ] column kind
|
|
400
|
-
* - [ ] column type
|
|
401
|
-
* - [ ] base off the type, check the settings
|
|
402
|
-
* - [ ] aggregation
|
|
403
|
-
* - [ ] verify groupBy agg columns, pivot agg columns and configuration agree
|
|
404
|
-
* - [ ] verify groupBy sort columns and tree column sort direction configuration agree
|
|
405
|
-
*/
|
|
406
428
|
|
|
407
|
-
|
|
429
|
+
// column selection
|
|
430
|
+
configuration.columns.forEach((column) => {
|
|
431
|
+
column.isSelected = Boolean(
|
|
432
|
+
data.groupExtendedColumns.find((col) => col.name === column.name) ??
|
|
433
|
+
data.selectColumns.find((col) => col.name === column.name),
|
|
434
|
+
);
|
|
435
|
+
});
|
|
436
|
+
return configuration;
|
|
408
437
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2020-present, Goldman Sachs
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export type DataCubeSettingValue =
|
|
18
|
+
| string
|
|
19
|
+
| number
|
|
20
|
+
| boolean
|
|
21
|
+
| object
|
|
22
|
+
| undefined;
|
|
23
|
+
|
|
24
|
+
export type DataCubeSettingValues = {
|
|
25
|
+
[key: string]: DataCubeSettingValue;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export enum DataCubeSettingGroup {
|
|
29
|
+
DEBUG = 'Debug',
|
|
30
|
+
GRID = 'Grid',
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export enum DataCubeSettingType {
|
|
34
|
+
BOOLEAN = 'boolean',
|
|
35
|
+
NUMERIC = 'numeric',
|
|
36
|
+
STRING = 'string',
|
|
37
|
+
ACTION = 'action',
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
41
|
+
export type DataCubeSetting<T extends DataCubeSettingValue = any> = {
|
|
42
|
+
key: string;
|
|
43
|
+
title: string;
|
|
44
|
+
group: string;
|
|
45
|
+
type: DataCubeSettingType;
|
|
46
|
+
defaultValue: T;
|
|
47
|
+
action?: ((newValue: T) => void) | undefined;
|
|
48
|
+
description?: string | undefined;
|
|
49
|
+
valueOptional?: boolean | undefined;
|
|
50
|
+
requiresReload?: boolean | undefined;
|
|
51
|
+
// numeric value specifics - TODO: we might want to break these downw to separate types
|
|
52
|
+
numericValueMin?: number | undefined;
|
|
53
|
+
numericValueMax?: number | undefined;
|
|
54
|
+
numericValueStep?: number | undefined;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export enum DataCubeSettingKey {
|
|
58
|
+
DEBUGGER__ENABLE_DEBUG_MODE = 'dataCube.debugger.enableDebugMode',
|
|
59
|
+
GRID_CLIENT__ROW_BUFFER = 'dataCube.grid-client.rowBuffer',
|
|
60
|
+
GRID_CLIENT__PURGE_CLOSED_ROW_NODES = 'dataCube.grid-client.purgeClosedRowNodes',
|
|
61
|
+
GRID_CLIENT__SUPPRESS_LARGE_DATASET_WARNING = 'dataCube.grid-client.suppressLargeDatasetWarning',
|
|
62
|
+
GRID_CLIENT__ACTION__REFRESH_FAILED_DATA_FETCHES = 'dataCube.grid-client.action.refreshFailedDataFetches',
|
|
63
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2020-present, Goldman Sachs
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
SerializationFactory,
|
|
19
|
+
usingConstantValueSchema,
|
|
20
|
+
type PlainObject,
|
|
21
|
+
} from '@finos/legend-shared';
|
|
22
|
+
import { DataCubeSource } from './DataCubeSource.js';
|
|
23
|
+
import { createModelSchema, primitive, raw } from 'serializr';
|
|
24
|
+
|
|
25
|
+
export class AdhocQueryDataCubeSource extends DataCubeSource {
|
|
26
|
+
runtime!: string;
|
|
27
|
+
model!: PlainObject;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const ADHOC_QUERY_DATA_CUBE_SOURCE_TYPE = 'adhocQuery';
|
|
31
|
+
|
|
32
|
+
export class RawAdhocQueryDataCubeSource {
|
|
33
|
+
query!: string;
|
|
34
|
+
runtime!: string;
|
|
35
|
+
model!: PlainObject;
|
|
36
|
+
|
|
37
|
+
static readonly serialization = new SerializationFactory(
|
|
38
|
+
createModelSchema(RawAdhocQueryDataCubeSource, {
|
|
39
|
+
_type: usingConstantValueSchema(ADHOC_QUERY_DATA_CUBE_SOURCE_TYPE),
|
|
40
|
+
model: raw(),
|
|
41
|
+
query: primitive(),
|
|
42
|
+
runtime: primitive(),
|
|
43
|
+
}),
|
|
44
|
+
);
|
|
45
|
+
}
|
|
@@ -18,7 +18,7 @@ import type { V1_ValueSpecification } from '@finos/legend-graph';
|
|
|
18
18
|
import type { DataCubeColumn } from './DataCubeColumn.js';
|
|
19
19
|
|
|
20
20
|
export abstract class DataCubeSource {
|
|
21
|
-
|
|
21
|
+
columns: DataCubeColumn[] = [];
|
|
22
22
|
query!: V1_ValueSpecification;
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
guaranteeNonNullable,
|
|
24
24
|
} from '@finos/legend-shared';
|
|
25
25
|
import type { DataCubeQuery } from '../core/models/DataCubeQuery.js';
|
|
26
|
+
import { DataCubeSettingKey } from '../core/DataCubeSetting.js';
|
|
26
27
|
|
|
27
28
|
// TODO: set a stack depth when we implement undo/redo
|
|
28
29
|
// const DATA_CUBE_MAX_SNAPSHOT_COUNT = 100;
|
|
@@ -64,7 +65,11 @@ export abstract class DataCubeQuerySnapshotController
|
|
|
64
65
|
const previousSnapshot = this.latestSnapshot;
|
|
65
66
|
this.latestSnapshot = snapshot;
|
|
66
67
|
|
|
67
|
-
if (
|
|
68
|
+
if (
|
|
69
|
+
this.view.dataCube.settings.getBooleanValue(
|
|
70
|
+
DataCubeSettingKey.DEBUGGER__ENABLE_DEBUG_MODE,
|
|
71
|
+
)
|
|
72
|
+
) {
|
|
68
73
|
this.view.engine.debugProcess(
|
|
69
74
|
`New Snapshot`,
|
|
70
75
|
['Publisher', this.getSnapshotSubscriberName()],
|
|
@@ -105,9 +110,16 @@ export class DataCubeQuerySnapshotManager {
|
|
|
105
110
|
subscriber.getSnapshotSubscriberName(),
|
|
106
111
|
);
|
|
107
112
|
if (existingSubscriber) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
// eslint-disable-next-line no-process-env
|
|
114
|
+
if (process.env.NODE_ENV === 'development') {
|
|
115
|
+
this.view.engine.logDebug(
|
|
116
|
+
`Subscriber with name '${subscriber.getSnapshotSubscriberName()}' already exists`,
|
|
117
|
+
);
|
|
118
|
+
} else {
|
|
119
|
+
throw new IllegalStateError(
|
|
120
|
+
`Subscriber with name '${subscriber.getSnapshotSubscriberName()}' already exists`,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
111
123
|
}
|
|
112
124
|
this.subscribers.push(subscriber);
|
|
113
125
|
}
|
|
@@ -57,7 +57,6 @@ class DataCubeTask {
|
|
|
57
57
|
export class DataCubeViewState {
|
|
58
58
|
readonly dataCube: DataCubeState;
|
|
59
59
|
readonly engine: DataCubeEngine;
|
|
60
|
-
|
|
61
60
|
readonly snapshotManager: DataCubeQuerySnapshotManager;
|
|
62
61
|
|
|
63
62
|
readonly info: DataCubeInfoState;
|
|
@@ -79,6 +78,8 @@ export class DataCubeViewState {
|
|
|
79
78
|
runningTasks: observable,
|
|
80
79
|
newTask: action,
|
|
81
80
|
endTask: action,
|
|
81
|
+
|
|
82
|
+
initialize: action,
|
|
82
83
|
});
|
|
83
84
|
|
|
84
85
|
this.dataCube = dataCube;
|
|
@@ -118,7 +119,7 @@ export class DataCubeViewState {
|
|
|
118
119
|
return task;
|
|
119
120
|
}
|
|
120
121
|
|
|
121
|
-
async initialize(
|
|
122
|
+
async initialize(query: DataCubeQuery) {
|
|
122
123
|
const task = this.newTask('Initializing');
|
|
123
124
|
try {
|
|
124
125
|
await Promise.all(
|
|
@@ -133,30 +134,20 @@ export class DataCubeViewState {
|
|
|
133
134
|
this.snapshotManager.registerSubscriber(state);
|
|
134
135
|
}),
|
|
135
136
|
);
|
|
136
|
-
const
|
|
137
|
-
if (!baseQuery) {
|
|
138
|
-
this.dataCube.alertAction({
|
|
139
|
-
message: `Initialization Failure: No initial input provided`,
|
|
140
|
-
prompt: `Make sure to either specify the initial input when setting up DataCube or the initial input getter in engine.`,
|
|
141
|
-
type: AlertType.ERROR,
|
|
142
|
-
actions: [],
|
|
143
|
-
});
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
const source = await this.engine.processQuerySource(baseQuery.source);
|
|
137
|
+
const source = await this.engine.processQuerySource(query.source);
|
|
147
138
|
runInAction(() => {
|
|
148
139
|
this._source = source;
|
|
149
140
|
});
|
|
150
141
|
const partialQuery = await this.engine.parseValueSpecification(
|
|
151
|
-
|
|
142
|
+
query.query,
|
|
152
143
|
);
|
|
153
144
|
const initialSnapshot = validateAndBuildQuerySnapshot(
|
|
154
145
|
partialQuery,
|
|
155
|
-
|
|
156
|
-
|
|
146
|
+
source,
|
|
147
|
+
query,
|
|
157
148
|
);
|
|
158
149
|
this.snapshotManager.broadcastSnapshot(initialSnapshot);
|
|
159
|
-
} catch (error
|
|
150
|
+
} catch (error) {
|
|
160
151
|
assertErrorThrown(error);
|
|
161
152
|
this.dataCube.alertAction({
|
|
162
153
|
message: `Initialization Failure: ${error.message}`,
|
|
@@ -42,14 +42,16 @@ import type { DataCubeExtendManagerState } from './DataCubeExtendManagerState.js
|
|
|
42
42
|
import {
|
|
43
43
|
EngineError,
|
|
44
44
|
PRIMITIVE_TYPE,
|
|
45
|
-
V1_deserializeValueSpecification,
|
|
46
45
|
V1_Lambda,
|
|
47
|
-
V1_serializeValueSpecification,
|
|
48
46
|
type V1_ValueSpecification,
|
|
49
47
|
} from '@finos/legend-graph';
|
|
50
48
|
import type { DataCubeColumnConfiguration } from '../../core/models/DataCubeConfiguration.js';
|
|
51
49
|
import type { DataCubeQuerySnapshotExtendedColumn } from '../../core/DataCubeQuerySnapshot.js';
|
|
52
|
-
import {
|
|
50
|
+
import {
|
|
51
|
+
_lambda,
|
|
52
|
+
_serializeValueSpecification,
|
|
53
|
+
_deserializeValueSpecification,
|
|
54
|
+
} from '../../core/DataCubeQueryBuilderUtils.js';
|
|
53
55
|
|
|
54
56
|
export abstract class DataCubeColumnBaseEditorState {
|
|
55
57
|
readonly uuid = uuid();
|
|
@@ -392,7 +394,7 @@ export class DataCubeNewColumnState extends DataCubeColumnBaseEditorState {
|
|
|
392
394
|
{
|
|
393
395
|
name: this.name,
|
|
394
396
|
type: returnType,
|
|
395
|
-
mapFn:
|
|
397
|
+
mapFn: _serializeValueSpecification(query),
|
|
396
398
|
},
|
|
397
399
|
this.isGroupLevel,
|
|
398
400
|
this.columnKind,
|
|
@@ -442,7 +444,7 @@ export class DataCubeExistingColumnEditorState extends DataCubeColumnBaseEditorS
|
|
|
442
444
|
|
|
443
445
|
override async getInitialCode(): Promise<string> {
|
|
444
446
|
return this.view.engine.getValueSpecificationCode(
|
|
445
|
-
|
|
447
|
+
_deserializeValueSpecification(this.initialData.mapFn),
|
|
446
448
|
true,
|
|
447
449
|
);
|
|
448
450
|
}
|
|
@@ -518,7 +520,7 @@ export class DataCubeExistingColumnEditorState extends DataCubeColumnBaseEditorS
|
|
|
518
520
|
{
|
|
519
521
|
name: this.name,
|
|
520
522
|
type: returnType,
|
|
521
|
-
mapFn:
|
|
523
|
+
mapFn: _serializeValueSpecification(query),
|
|
522
524
|
},
|
|
523
525
|
this.isGroupLevel,
|
|
524
526
|
this.columnKind,
|