@finos/legend-application-data-cube 0.2.0 → 0.2.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.
- package/lib/__lib__/LegendDataCubeNavigation.d.ts +1 -1
- package/lib/__lib__/LegendDataCubeNavigation.d.ts.map +1 -1
- package/lib/components/LegendDataCubeWebApplication.d.ts.map +1 -1
- package/lib/components/LegendDataCubeWebApplication.js +1 -14
- package/lib/components/LegendDataCubeWebApplication.js.map +1 -1
- package/lib/components/query-builder/LegendDataCubeQueryBuilder.d.ts.map +1 -1
- package/lib/components/query-builder/LegendDataCubeQueryBuilder.js +23 -23
- package/lib/components/query-builder/LegendDataCubeQueryBuilder.js.map +1 -1
- package/lib/components/query-builder/source-builder/LegendQueryDataCubeSourceBuilder.d.ts.map +1 -1
- package/lib/components/query-builder/source-builder/LegendQueryDataCubeSourceBuilder.js +8 -1
- package/lib/components/query-builder/source-builder/LegendQueryDataCubeSourceBuilder.js.map +1 -1
- package/lib/index.css +1 -1
- package/lib/package.json +2 -2
- package/lib/stores/LegendDataCubeCacheManager.d.ts +15 -6
- package/lib/stores/LegendDataCubeCacheManager.d.ts.map +1 -1
- package/lib/stores/LegendDataCubeCacheManager.js +68 -41
- package/lib/stores/LegendDataCubeCacheManager.js.map +1 -1
- package/lib/stores/LegendDataCubeDataCubeEngine.d.ts +5 -7
- package/lib/stores/LegendDataCubeDataCubeEngine.d.ts.map +1 -1
- package/lib/stores/LegendDataCubeDataCubeEngine.js +80 -105
- package/lib/stores/LegendDataCubeDataCubeEngine.js.map +1 -1
- package/lib/stores/query-builder/LegendDataCubeNewQueryState.d.ts.map +1 -1
- package/lib/stores/query-builder/LegendDataCubeNewQueryState.js +10 -10
- package/lib/stores/query-builder/LegendDataCubeNewQueryState.js.map +1 -1
- package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.d.ts +0 -1
- package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.d.ts.map +1 -1
- package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.js +18 -9
- package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.js.map +1 -1
- package/lib/stores/query-builder/source-builder/AdhocQueryDataCubeSourceBuilderState.d.ts +1 -1
- package/lib/stores/query-builder/source-builder/AdhocQueryDataCubeSourceBuilderState.d.ts.map +1 -1
- package/lib/stores/query-builder/source-builder/AdhocQueryDataCubeSourceBuilderState.js +1 -1
- package/lib/stores/query-builder/source-builder/AdhocQueryDataCubeSourceBuilderState.js.map +1 -1
- package/lib/stores/query-builder/source-builder/LegendDataCubeSourceBuilderState.d.ts +4 -3
- package/lib/stores/query-builder/source-builder/LegendDataCubeSourceBuilderState.d.ts.map +1 -1
- package/lib/stores/query-builder/source-builder/LegendDataCubeSourceBuilderState.js +5 -2
- package/lib/stores/query-builder/source-builder/LegendDataCubeSourceBuilderState.js.map +1 -1
- package/lib/stores/query-builder/source-builder/LegendQueryDataCubeSourceBuilderState.d.ts +3 -2
- package/lib/stores/query-builder/source-builder/LegendQueryDataCubeSourceBuilderState.d.ts.map +1 -1
- package/lib/stores/query-builder/source-builder/LegendQueryDataCubeSourceBuilderState.js +6 -1
- package/lib/stores/query-builder/source-builder/LegendQueryDataCubeSourceBuilderState.js.map +1 -1
- package/package.json +11 -11
- package/src/__lib__/LegendDataCubeNavigation.ts +1 -1
- package/src/components/LegendDataCubeWebApplication.tsx +1 -25
- package/src/components/query-builder/LegendDataCubeQueryBuilder.tsx +26 -27
- package/src/components/query-builder/source-builder/LegendQueryDataCubeSourceBuilder.tsx +17 -1
- package/src/stores/LegendDataCubeCacheManager.ts +82 -44
- package/src/stores/LegendDataCubeDataCubeEngine.ts +116 -142
- package/src/stores/query-builder/LegendDataCubeNewQueryState.tsx +12 -18
- package/src/stores/query-builder/LegendDataCubeQueryBuilderStore.tsx +26 -10
- package/src/stores/query-builder/source-builder/AdhocQueryDataCubeSourceBuilderState.ts +1 -1
- package/src/stores/query-builder/source-builder/LegendDataCubeSourceBuilderState.ts +8 -4
- package/src/stores/query-builder/source-builder/LegendQueryDataCubeSourceBuilderState.ts +11 -2
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import {
|
|
18
18
|
V1_Lambda,
|
|
19
|
-
V1_ValueSpecification,
|
|
19
|
+
type V1_ValueSpecification,
|
|
20
20
|
type V1_EngineServerClient,
|
|
21
21
|
V1_PureGraphManager,
|
|
22
22
|
type V1_PureModelContext,
|
|
@@ -70,7 +70,8 @@ import {
|
|
|
70
70
|
V1_Table,
|
|
71
71
|
V1_TestAuthenticationStrategy,
|
|
72
72
|
V1_VarChar,
|
|
73
|
-
|
|
73
|
+
PackageableElementPointerType,
|
|
74
|
+
DatabaseType,
|
|
74
75
|
} from '@finos/legend-graph';
|
|
75
76
|
import {
|
|
76
77
|
_elementPtr,
|
|
@@ -79,17 +80,13 @@ import {
|
|
|
79
80
|
type CompletionItem,
|
|
80
81
|
_function,
|
|
81
82
|
DataCubeFunction,
|
|
82
|
-
_deserializeLambda,
|
|
83
83
|
AdhocQueryDataCubeSource,
|
|
84
84
|
ADHOC_QUERY_DATA_CUBE_SOURCE_TYPE,
|
|
85
85
|
RawAdhocQueryDataCubeSource,
|
|
86
86
|
_lambda,
|
|
87
|
-
_serializeValueSpecification,
|
|
88
|
-
_deserializeValueSpecification,
|
|
89
87
|
_defaultPrimitiveTypeValue,
|
|
90
88
|
type DataCubeExecutionOptions,
|
|
91
89
|
CachedDataCubeSource,
|
|
92
|
-
type DataCubeQuerySnapshot,
|
|
93
90
|
} from '@finos/legend-data-cube';
|
|
94
91
|
import {
|
|
95
92
|
isNonNullable,
|
|
@@ -102,10 +99,11 @@ import {
|
|
|
102
99
|
at,
|
|
103
100
|
assertType,
|
|
104
101
|
guaranteeType,
|
|
105
|
-
|
|
102
|
+
guaranteeNonNullable,
|
|
103
|
+
filterByType,
|
|
106
104
|
} from '@finos/legend-shared';
|
|
107
105
|
import type { LegendDataCubeApplicationStore } from './LegendDataCubeBaseStore.js';
|
|
108
|
-
import {
|
|
106
|
+
import { LegendDataCubeDataCubeCacheManager } from './LegendDataCubeCacheManager.js';
|
|
109
107
|
import { APPLICATION_EVENT } from '@finos/legend-application';
|
|
110
108
|
import {
|
|
111
109
|
LEGEND_QUERY_DATA_CUBE_SOURCE_TYPE,
|
|
@@ -123,7 +121,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
123
121
|
private readonly _depotServerClient: DepotServerClient;
|
|
124
122
|
private readonly _engineServerClient: V1_EngineServerClient;
|
|
125
123
|
private readonly _graphManager: V1_PureGraphManager;
|
|
126
|
-
private readonly _cacheManager:
|
|
124
|
+
private readonly _cacheManager: LegendDataCubeDataCubeCacheManager;
|
|
127
125
|
|
|
128
126
|
constructor(
|
|
129
127
|
application: LegendDataCubeApplicationStore,
|
|
@@ -137,7 +135,15 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
137
135
|
this._depotServerClient = depotServerClient;
|
|
138
136
|
this._engineServerClient = engineServerClient;
|
|
139
137
|
this._graphManager = graphManager;
|
|
140
|
-
this._cacheManager = new
|
|
138
|
+
this._cacheManager = new LegendDataCubeDataCubeCacheManager();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async initializeCacheManager() {
|
|
142
|
+
await this._cacheManager.initialize();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async disposeCacheManager() {
|
|
146
|
+
await this._cacheManager.dispose();
|
|
141
147
|
}
|
|
142
148
|
|
|
143
149
|
// ---------------------------------- IMPLEMENTATION ----------------------------------
|
|
@@ -159,7 +165,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
159
165
|
try {
|
|
160
166
|
source.columns = (
|
|
161
167
|
await this._getLambdaRelationType(
|
|
162
|
-
|
|
168
|
+
this.serializeValueSpecification(_lambda([], [source.query])),
|
|
163
169
|
source.model,
|
|
164
170
|
)
|
|
165
171
|
).columns;
|
|
@@ -189,14 +195,18 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
189
195
|
);
|
|
190
196
|
const source = new LegendQueryDataCubeSource();
|
|
191
197
|
source.info = queryInfo;
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
198
|
+
|
|
199
|
+
source.lambda = guaranteeType(
|
|
200
|
+
this.deserializeValueSpecification(
|
|
201
|
+
await this._engineServerClient.grammarToJSON_lambda(
|
|
202
|
+
queryInfo.content,
|
|
203
|
+
'',
|
|
204
|
+
undefined,
|
|
205
|
+
undefined,
|
|
206
|
+
false,
|
|
207
|
+
),
|
|
199
208
|
),
|
|
209
|
+
V1_Lambda,
|
|
200
210
|
);
|
|
201
211
|
source.mapping = executionContext.mapping;
|
|
202
212
|
source.runtime = executionContext.runtime;
|
|
@@ -215,18 +225,22 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
215
225
|
),
|
|
216
226
|
);
|
|
217
227
|
source.query = at(source.lambda.body, 0);
|
|
228
|
+
// use the default parameter values from the query
|
|
229
|
+
//
|
|
230
|
+
// TODO?: we should probably allow configuring the parameters?
|
|
231
|
+
// this would mean we need to create first-class support for parameters in DataCube component
|
|
218
232
|
const parameterValues = await Promise.all(
|
|
219
233
|
source.lambda.parameters.map(async (parameter) => {
|
|
220
234
|
if (parameter.genericType?.rawType instanceof V1_PackageableType) {
|
|
221
235
|
const paramValue = new V1_ParameterValue();
|
|
222
236
|
paramValue.name = parameter.name;
|
|
223
237
|
const type = parameter.genericType.rawType.fullPath;
|
|
224
|
-
const
|
|
238
|
+
const defaultValue = queryInfo.defaultParameterValues?.find(
|
|
225
239
|
(val) => val.name === parameter.name,
|
|
226
240
|
)?.content;
|
|
227
241
|
paramValue.value =
|
|
228
|
-
|
|
229
|
-
? await this.parseValueSpecification(
|
|
242
|
+
defaultValue !== undefined
|
|
243
|
+
? await this.parseValueSpecification(defaultValue)
|
|
230
244
|
: {
|
|
231
245
|
_type: V1_deserializeRawValueSpecificationType(type),
|
|
232
246
|
value: _defaultPrimitiveTypeValue(type),
|
|
@@ -240,7 +254,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
240
254
|
try {
|
|
241
255
|
source.columns = (
|
|
242
256
|
await this._getLambdaRelationType(
|
|
243
|
-
|
|
257
|
+
this.serializeValueSpecification(source.lambda),
|
|
244
258
|
source.model,
|
|
245
259
|
)
|
|
246
260
|
).columns;
|
|
@@ -264,7 +278,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
264
278
|
returnSourceInformation?: boolean | undefined,
|
|
265
279
|
) {
|
|
266
280
|
try {
|
|
267
|
-
return
|
|
281
|
+
return this.deserializeValueSpecification(
|
|
268
282
|
await this._engineServerClient.grammarToJSON_valueSpecification(
|
|
269
283
|
code,
|
|
270
284
|
'',
|
|
@@ -294,7 +308,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
294
308
|
pretty?: boolean | undefined,
|
|
295
309
|
) {
|
|
296
310
|
return this._graphManager.valueSpecificationToPureCode(
|
|
297
|
-
|
|
311
|
+
this.serializeValueSpecification(value),
|
|
298
312
|
pretty,
|
|
299
313
|
);
|
|
300
314
|
}
|
|
@@ -337,7 +351,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
337
351
|
) {
|
|
338
352
|
try {
|
|
339
353
|
return await this._getQueryRelationType(
|
|
340
|
-
|
|
354
|
+
this.serializeValueSpecification(query),
|
|
341
355
|
source,
|
|
342
356
|
);
|
|
343
357
|
} catch (error) {
|
|
@@ -415,32 +429,26 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
415
429
|
options,
|
|
416
430
|
);
|
|
417
431
|
} else if (source instanceof CachedDataCubeSource) {
|
|
418
|
-
//execute plan
|
|
432
|
+
// get the execute plan to extract the generated SQL to run against cached DB
|
|
419
433
|
const executionPlan = await this.generateExecutionPlan(
|
|
420
434
|
query,
|
|
421
435
|
source.model,
|
|
422
436
|
[],
|
|
423
437
|
options,
|
|
424
438
|
);
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
`Can't generate sql for the query`,
|
|
434
|
-
),
|
|
435
|
-
)
|
|
436
|
-
.at(-1)?.sqlQuery;
|
|
437
|
-
}
|
|
438
|
-
assertNonNullable(sql, `Can't generate sql for the query`);
|
|
439
|
+
const sql = guaranteeNonNullable(
|
|
440
|
+
executionPlan instanceof V1_SimpleExecutionPlan
|
|
441
|
+
? executionPlan.rootExecutionNode.executionNodes
|
|
442
|
+
.filter(filterByType(V1_SQLExecutionNode))
|
|
443
|
+
.at(-1)?.sqlQuery
|
|
444
|
+
: undefined,
|
|
445
|
+
`Can't process execution plan: failed to extract generated SQL`,
|
|
446
|
+
);
|
|
439
447
|
const endTime = performance.now();
|
|
440
448
|
return {
|
|
441
449
|
executedQuery: await queryCodePromise,
|
|
442
450
|
executedSQL: sql,
|
|
443
|
-
result: await this._cacheManager.
|
|
451
|
+
result: await this._cacheManager.runSQLQuery(sql),
|
|
444
452
|
executionTime: endTime - startTime,
|
|
445
453
|
};
|
|
446
454
|
} else {
|
|
@@ -451,17 +459,16 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
451
459
|
assertType(
|
|
452
460
|
result,
|
|
453
461
|
TDSExecutionResult,
|
|
454
|
-
`Can't
|
|
462
|
+
`Can't process execution result: expected tabular data set format`,
|
|
455
463
|
);
|
|
456
464
|
const endTime = performance.now();
|
|
457
465
|
const queryCode = await queryCodePromise;
|
|
458
|
-
const sql =
|
|
466
|
+
const sql = guaranteeNonNullable(
|
|
459
467
|
result.activities?.[0] instanceof RelationalExecutionActivities
|
|
460
468
|
? result.activities[0].sql
|
|
461
|
-
: undefined
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
}
|
|
469
|
+
: undefined,
|
|
470
|
+
`Can't process execution result: failed to extract generated SQL`,
|
|
471
|
+
);
|
|
465
472
|
return {
|
|
466
473
|
result: result,
|
|
467
474
|
executedQuery: queryCode,
|
|
@@ -493,16 +500,6 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
493
500
|
return undefined;
|
|
494
501
|
}
|
|
495
502
|
|
|
496
|
-
override processInitialSnapshot(
|
|
497
|
-
source: DataCubeSource,
|
|
498
|
-
snapshot: DataCubeQuerySnapshot,
|
|
499
|
-
): DataCubeQuerySnapshot {
|
|
500
|
-
if (source instanceof LegendQueryDataCubeSource) {
|
|
501
|
-
snapshot.data.configuration.name = source.info.name;
|
|
502
|
-
}
|
|
503
|
-
return snapshot;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
503
|
// ---------------------------------- UTILITIES ----------------------------------
|
|
507
504
|
|
|
508
505
|
private async _getQueryRelationType(
|
|
@@ -555,7 +552,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
555
552
|
(process.env.NODE_ENV === 'development'
|
|
556
553
|
? PureClientVersion.VX_X_X
|
|
557
554
|
: undefined),
|
|
558
|
-
function:
|
|
555
|
+
function: this.serializeValueSpecification(query),
|
|
559
556
|
model,
|
|
560
557
|
context: serialize(
|
|
561
558
|
V1_rawBaseExecutionContextModelSchema,
|
|
@@ -577,13 +574,8 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
577
574
|
): Promise<V1_ExecutionPlan> {
|
|
578
575
|
return V1_deserializeExecutionPlan(
|
|
579
576
|
await this._engineServerClient.generatePlan({
|
|
580
|
-
clientVersion:
|
|
581
|
-
|
|
582
|
-
// eslint-disable-next-line no-process-env
|
|
583
|
-
(process.env.NODE_ENV === 'development'
|
|
584
|
-
? PureClientVersion.VX_X_X
|
|
585
|
-
: undefined),
|
|
586
|
-
function: _serializeValueSpecification(query),
|
|
577
|
+
clientVersion: PureClientVersion.VX_X_X,
|
|
578
|
+
function: this.serializeValueSpecification(query),
|
|
587
579
|
model: serialize(model),
|
|
588
580
|
context: serialize(
|
|
589
581
|
V1_rawBaseExecutionContextModelSchema,
|
|
@@ -601,110 +593,92 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
|
|
|
601
593
|
override async initializeCache(
|
|
602
594
|
source: DataCubeSource,
|
|
603
595
|
): Promise<CachedDataCubeSource | undefined> {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
const result = resultQuery.result;
|
|
620
|
-
await this._cacheManager.initializeDuckDb(result);
|
|
621
|
-
return this._synthesizeCachedSource(source, result.builder);
|
|
622
|
-
}
|
|
623
|
-
return undefined;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
override async clearCache() {
|
|
627
|
-
await this._cacheManager.clearDuckDb();
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
// --------------------------------- CACHING UTILITY -------------------------------
|
|
631
|
-
|
|
632
|
-
private _synthesizeCachedSource(
|
|
633
|
-
source: LegendQueryDataCubeSource,
|
|
634
|
-
builder: TDSBuilder,
|
|
635
|
-
) {
|
|
636
|
-
const cachedSource = new CachedDataCubeSource();
|
|
637
|
-
cachedSource.columns = source.columns;
|
|
638
|
-
cachedSource.query = this._synthesizeQuery([
|
|
639
|
-
'local::duckdb::cachedStore',
|
|
640
|
-
'main',
|
|
641
|
-
'cached_tbl',
|
|
642
|
-
]);
|
|
643
|
-
cachedSource.model = this._synthesizeModel(builder);
|
|
644
|
-
cachedSource.runtime = 'local::duckdb::runtime';
|
|
645
|
-
return cachedSource;
|
|
646
|
-
}
|
|
596
|
+
const cacheQuery = guaranteeNonNullable(
|
|
597
|
+
this.buildExecutionContext(source),
|
|
598
|
+
`Can't initialize cache: failed to build cache query`,
|
|
599
|
+
);
|
|
600
|
+
cacheQuery.parameters.unshift(source.query);
|
|
601
|
+
const result = await this.executeQuery(
|
|
602
|
+
_lambda([], [cacheQuery]),
|
|
603
|
+
source,
|
|
604
|
+
undefined,
|
|
605
|
+
);
|
|
606
|
+
const {
|
|
607
|
+
schema: schemaName,
|
|
608
|
+
table: tableName,
|
|
609
|
+
rowCount,
|
|
610
|
+
} = await this._cacheManager.cache(result.result);
|
|
647
611
|
|
|
648
|
-
|
|
649
|
-
const
|
|
650
|
-
classInstance.type = V1_ClassInstanceType.RELATION_STORE_ACCESSOR;
|
|
651
|
-
const storeAccessor = new V1_RelationStoreAccessor();
|
|
652
|
-
storeAccessor.path = databaseAccessor;
|
|
653
|
-
classInstance.value = storeAccessor;
|
|
654
|
-
return classInstance;
|
|
655
|
-
}
|
|
612
|
+
// model
|
|
613
|
+
const pacakgePath = 'local';
|
|
656
614
|
|
|
657
|
-
private _synthesizeModel(builder: TDSBuilder) {
|
|
658
|
-
// synthesize table
|
|
659
615
|
const table = new V1_Table();
|
|
660
|
-
table.name =
|
|
661
|
-
table.columns = builder.columns.map((col) => {
|
|
616
|
+
table.name = tableName;
|
|
617
|
+
table.columns = result.result.builder.columns.map((col) => {
|
|
662
618
|
const column = new V1_Column();
|
|
663
619
|
column.name = col.name;
|
|
664
620
|
column.type = this._getColumnType(col.type);
|
|
665
621
|
return column;
|
|
666
622
|
});
|
|
667
|
-
|
|
623
|
+
|
|
668
624
|
const schema = new V1_Schema();
|
|
669
|
-
schema.name =
|
|
625
|
+
schema.name = schemaName;
|
|
670
626
|
schema.tables = [table];
|
|
671
|
-
// synthesize database
|
|
672
627
|
const database = new V1_Database();
|
|
673
|
-
database.name = '
|
|
674
|
-
database.package =
|
|
628
|
+
database.name = 'db';
|
|
629
|
+
database.package = pacakgePath;
|
|
675
630
|
database.schemas = [schema];
|
|
676
631
|
|
|
677
|
-
// build connection
|
|
678
632
|
const connection = new V1_RelationalDatabaseConnection();
|
|
679
|
-
connection.databaseType =
|
|
680
|
-
connection.type =
|
|
633
|
+
connection.databaseType = DatabaseType.DuckDB;
|
|
634
|
+
connection.type = DatabaseType.DuckDB;
|
|
681
635
|
const dataSourceSpec = new V1_DuckDBDatasourceSpecification();
|
|
682
|
-
dataSourceSpec.path = '/
|
|
683
|
-
connection.store =
|
|
636
|
+
dataSourceSpec.path = '/tmpFile';
|
|
637
|
+
connection.store = database.path;
|
|
684
638
|
connection.datasourceSpecification = dataSourceSpec;
|
|
685
639
|
connection.authenticationStrategy = new V1_TestAuthenticationStrategy();
|
|
686
640
|
|
|
687
|
-
// build runtime
|
|
688
641
|
const runtime = new V1_EngineRuntime();
|
|
689
642
|
const storeConnections = new V1_StoreConnections();
|
|
690
643
|
storeConnections.store = new V1_PackageableElementPointer(
|
|
691
|
-
|
|
692
|
-
|
|
644
|
+
PackageableElementPointerType.STORE,
|
|
645
|
+
database.path,
|
|
693
646
|
);
|
|
694
|
-
const
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
storeConnections.storeConnections = [
|
|
647
|
+
const identifiedConnection = new V1_IdentifiedConnection();
|
|
648
|
+
identifiedConnection.connection = connection;
|
|
649
|
+
identifiedConnection.id = 'c0';
|
|
650
|
+
storeConnections.storeConnections = [identifiedConnection];
|
|
698
651
|
runtime.connections = [storeConnections];
|
|
699
652
|
|
|
700
653
|
const packageableRuntime = new V1_PackageableRuntime();
|
|
701
654
|
packageableRuntime.runtimeValue = runtime;
|
|
702
|
-
packageableRuntime.package =
|
|
703
|
-
packageableRuntime.name = '
|
|
655
|
+
packageableRuntime.package = pacakgePath;
|
|
656
|
+
packageableRuntime.name = 'rt';
|
|
657
|
+
|
|
658
|
+
const model = new V1_PureModelContextData();
|
|
659
|
+
model.elements = [database, packageableRuntime];
|
|
660
|
+
|
|
661
|
+
// query
|
|
662
|
+
const query = new V1_ClassInstance();
|
|
663
|
+
query.type = V1_ClassInstanceType.RELATION_STORE_ACCESSOR;
|
|
664
|
+
const storeAccessor = new V1_RelationStoreAccessor();
|
|
665
|
+
storeAccessor.path = [database.path, schema.name, table.name];
|
|
666
|
+
query.value = storeAccessor;
|
|
667
|
+
|
|
668
|
+
const cachedSource = new CachedDataCubeSource();
|
|
669
|
+
cachedSource.columns = source.columns;
|
|
670
|
+
cachedSource.query = query;
|
|
671
|
+
cachedSource.model = model;
|
|
672
|
+
cachedSource.runtime = packageableRuntime.path;
|
|
673
|
+
cachedSource.db = database.path;
|
|
674
|
+
cachedSource.schema = schema.name;
|
|
675
|
+
cachedSource.table = table.name;
|
|
676
|
+
cachedSource.count = rowCount;
|
|
677
|
+
return cachedSource;
|
|
678
|
+
}
|
|
704
679
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
return pmcd;
|
|
680
|
+
override async disposeCache(source: CachedDataCubeSource) {
|
|
681
|
+
await this._cacheManager.disposeCache(source);
|
|
708
682
|
}
|
|
709
683
|
|
|
710
684
|
// TODO: need a better way to infer datatype from tds builder
|
|
@@ -29,9 +29,7 @@ import {
|
|
|
29
29
|
type LegendDataCubeSourceBuilderState,
|
|
30
30
|
} from './source-builder/LegendDataCubeSourceBuilderState.js';
|
|
31
31
|
import {
|
|
32
|
-
_selectFunction,
|
|
33
32
|
type DataCubeAlertService,
|
|
34
|
-
DataCubeQuery,
|
|
35
33
|
DEFAULT_TOOL_PANEL_WINDOW_CONFIG,
|
|
36
34
|
type DisplayState,
|
|
37
35
|
} from '@finos/legend-data-cube';
|
|
@@ -44,6 +42,8 @@ import {
|
|
|
44
42
|
} from './LegendDataCubeQueryBuilderStore.js';
|
|
45
43
|
import { generateQueryBuilderRoute } from '../../__lib__/LegendDataCubeNavigation.js';
|
|
46
44
|
|
|
45
|
+
const DEFAULT_SOURCE_TYPE = LegendDataCubeSourceBuilderType.LEGEND_QUERY;
|
|
46
|
+
|
|
47
47
|
export class LegendDataCubeNewQueryState {
|
|
48
48
|
private readonly _application: LegendDataCubeApplicationStore;
|
|
49
49
|
private readonly _store: LegendDataCubeQueryBuilderStore;
|
|
@@ -76,9 +76,7 @@ export class LegendDataCubeNewQueryState {
|
|
|
76
76
|
},
|
|
77
77
|
);
|
|
78
78
|
|
|
79
|
-
this.sourceBuilder = this.createSourceBuilder(
|
|
80
|
-
LegendDataCubeSourceBuilderType.LEGEND_QUERY,
|
|
81
|
-
);
|
|
79
|
+
this.sourceBuilder = this.createSourceBuilder(DEFAULT_SOURCE_TYPE);
|
|
82
80
|
}
|
|
83
81
|
|
|
84
82
|
changeSourceBuilder(
|
|
@@ -115,31 +113,27 @@ export class LegendDataCubeNewQueryState {
|
|
|
115
113
|
}
|
|
116
114
|
|
|
117
115
|
async finalize(sourceData?: PlainObject) {
|
|
118
|
-
if (!this.sourceBuilder.isValid
|
|
116
|
+
if (!sourceData && !this.sourceBuilder.isValid) {
|
|
119
117
|
throw new IllegalStateError(`Can't generate query: source is not valid`);
|
|
120
118
|
}
|
|
121
119
|
|
|
122
120
|
this.finalizeState.inProgress();
|
|
123
121
|
try {
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
const processedSource = await this._engine.processQuerySource(source);
|
|
127
|
-
query.source = source;
|
|
128
|
-
query.query = await this._engine.getValueSpecificationCode(
|
|
129
|
-
_selectFunction(processedSource.columns),
|
|
122
|
+
const query = await this._engine.generateBaseQuery(
|
|
123
|
+
sourceData ?? (await this.sourceBuilder.generateSourceData()),
|
|
130
124
|
);
|
|
125
|
+
if (query.configuration) {
|
|
126
|
+
this.sourceBuilder.finalizeConfiguration(query.configuration);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// reset
|
|
131
130
|
this._store.setBuilder(new LegendDataCubeQueryBuilderState(query));
|
|
132
131
|
// only update the route instead of reloading in case we are creating
|
|
133
132
|
// a new query when we are editing another query
|
|
134
133
|
this._application.navigationService.navigator.updateCurrentLocation(
|
|
135
134
|
generateQueryBuilderRoute(null),
|
|
136
135
|
);
|
|
137
|
-
|
|
138
|
-
// reset
|
|
139
|
-
this.changeSourceBuilder(
|
|
140
|
-
LegendDataCubeSourceBuilderType.LEGEND_QUERY,
|
|
141
|
-
true,
|
|
142
|
-
);
|
|
136
|
+
this.changeSourceBuilder(DEFAULT_SOURCE_TYPE, true);
|
|
143
137
|
this.display.close();
|
|
144
138
|
this.finalizeState.pass();
|
|
145
139
|
} catch (error) {
|
|
@@ -43,7 +43,10 @@ import {
|
|
|
43
43
|
} from '@finos/legend-shared';
|
|
44
44
|
import type { LegendDataCubeDataCubeEngine } from '../LegendDataCubeDataCubeEngine.js';
|
|
45
45
|
import { LegendDataCubeQuerySaver } from '../../components/query-builder/LegendDataCubeQuerySaver.js';
|
|
46
|
-
import {
|
|
46
|
+
import {
|
|
47
|
+
generateQueryBuilderRoute,
|
|
48
|
+
LEGEND_DATA_CUBE_ROUTE_PATTERN_TOKEN,
|
|
49
|
+
} from '../../__lib__/LegendDataCubeNavigation.js';
|
|
47
50
|
import { LegendDataCubeQueryLoaderState } from './LegendDataCubeQueryLoaderState.js';
|
|
48
51
|
import {
|
|
49
52
|
LegendDataCubeUserDataKey,
|
|
@@ -68,7 +71,6 @@ export class LegendDataCubeQueryBuilderState {
|
|
|
68
71
|
|
|
69
72
|
query: observable,
|
|
70
73
|
persistentQuery: observable,
|
|
71
|
-
setPersistentQuery: action,
|
|
72
74
|
});
|
|
73
75
|
|
|
74
76
|
this.query = query;
|
|
@@ -78,12 +80,6 @@ export class LegendDataCubeQueryBuilderState {
|
|
|
78
80
|
setDataCube(val: DataCubeAPI | undefined) {
|
|
79
81
|
this.dataCube = val;
|
|
80
82
|
}
|
|
81
|
-
|
|
82
|
-
setPersistentQuery(val: PersistentDataCubeQuery) {
|
|
83
|
-
this.persistentQuery = val;
|
|
84
|
-
this.query = DataCubeQuery.serialization.fromJson(val.content);
|
|
85
|
-
this.startTime = Date.now();
|
|
86
|
-
}
|
|
87
83
|
}
|
|
88
84
|
|
|
89
85
|
export class LegendDataCubeQueryBuilderStore {
|
|
@@ -154,9 +150,31 @@ export class LegendDataCubeQueryBuilderStore {
|
|
|
154
150
|
}
|
|
155
151
|
|
|
156
152
|
async loadQuery(queryId: string | undefined) {
|
|
153
|
+
// internalize the parameters and clean them from the URL
|
|
154
|
+
const sourceData =
|
|
155
|
+
this.application.navigationService.navigator.getCurrentLocationParameterValue(
|
|
156
|
+
LEGEND_DATA_CUBE_ROUTE_PATTERN_TOKEN.SOURCE_DATA,
|
|
157
|
+
);
|
|
158
|
+
if (sourceData && !queryId) {
|
|
159
|
+
this.application.navigationService.navigator.updateCurrentLocation(
|
|
160
|
+
generateQueryBuilderRoute(null),
|
|
161
|
+
);
|
|
162
|
+
// populate the new query state if source data is specified
|
|
163
|
+
try {
|
|
164
|
+
await this.newQueryState.finalize(JSON.parse(atob(sourceData)));
|
|
165
|
+
} catch (error) {
|
|
166
|
+
assertErrorThrown(error);
|
|
167
|
+
this.alertService.alertError(error, {
|
|
168
|
+
message: `Query Creation Failure: Can't materialize query source from source data. Error: ${error.message}`,
|
|
169
|
+
});
|
|
170
|
+
this.setBuilder(undefined);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
157
174
|
if (queryId !== this.builder?.persistentQuery?.id) {
|
|
158
175
|
if (!queryId) {
|
|
159
176
|
this.setBuilder(undefined);
|
|
177
|
+
this.loader.display.open();
|
|
160
178
|
return;
|
|
161
179
|
}
|
|
162
180
|
|
|
@@ -244,7 +262,6 @@ export class LegendDataCubeQueryBuilderStore {
|
|
|
244
262
|
this.application.navigationService.navigator.updateCurrentLocation(
|
|
245
263
|
generateQueryBuilderRoute(newQuery.id),
|
|
246
264
|
);
|
|
247
|
-
this.builder.setPersistentQuery(persistentQuery);
|
|
248
265
|
this.updateWindowTitle(persistentQuery);
|
|
249
266
|
|
|
250
267
|
this.saverDisplay.close();
|
|
@@ -291,7 +308,6 @@ export class LegendDataCubeQueryBuilderStore {
|
|
|
291
308
|
} else {
|
|
292
309
|
await this.baseStore.graphManager.updateDataCubeQuery(persistentQuery);
|
|
293
310
|
}
|
|
294
|
-
this.builder.setPersistentQuery(persistentQuery);
|
|
295
311
|
this.updateWindowTitle(persistentQuery);
|
|
296
312
|
|
|
297
313
|
this.saverDisplay.close();
|
|
@@ -29,7 +29,7 @@ export class AdhocQueryDataCubeSourceBuilderState extends LegendDataCubeSourceBu
|
|
|
29
29
|
return false;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
override
|
|
32
|
+
override generateSourceData(): Promise<PlainObject> {
|
|
33
33
|
throw new Error('Method not implemented.');
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { type PlainObject } from '@finos/legend-shared';
|
|
18
18
|
import type { LegendDataCubeApplicationStore } from '../../LegendDataCubeBaseStore.js';
|
|
19
19
|
import type { LegendDataCubeDataCubeEngine } from '../../LegendDataCubeDataCubeEngine.js';
|
|
20
|
+
import type { DataCubeConfiguration } from '@finos/legend-data-cube';
|
|
20
21
|
|
|
21
22
|
export enum LegendDataCubeSourceBuilderType {
|
|
22
23
|
LEGEND_QUERY = 'Legend Query',
|
|
@@ -27,8 +28,6 @@ export abstract class LegendDataCubeSourceBuilderState {
|
|
|
27
28
|
protected readonly _application: LegendDataCubeApplicationStore;
|
|
28
29
|
protected readonly _engine: LegendDataCubeDataCubeEngine;
|
|
29
30
|
|
|
30
|
-
readonly buildState = ActionState.create();
|
|
31
|
-
|
|
32
31
|
constructor(
|
|
33
32
|
application: LegendDataCubeApplicationStore,
|
|
34
33
|
engine: LegendDataCubeDataCubeEngine,
|
|
@@ -39,5 +38,10 @@ export abstract class LegendDataCubeSourceBuilderState {
|
|
|
39
38
|
|
|
40
39
|
abstract get label(): LegendDataCubeSourceBuilderType;
|
|
41
40
|
abstract get isValid(): boolean;
|
|
42
|
-
abstract
|
|
41
|
+
abstract generateSourceData(): Promise<PlainObject>;
|
|
42
|
+
|
|
43
|
+
/* Modifies the configuration of the finalized DataCube query based on the source builder */
|
|
44
|
+
finalizeConfiguration(configuration: DataCubeConfiguration) {
|
|
45
|
+
// do nothing
|
|
46
|
+
}
|
|
43
47
|
}
|
|
@@ -39,7 +39,10 @@ import { RawLegendQueryDataCubeSource } from '../../model/LegendQueryDataCubeSou
|
|
|
39
39
|
import { APPLICATION_EVENT } from '@finos/legend-application';
|
|
40
40
|
import type { LegendDataCubeDataCubeEngine } from '../../LegendDataCubeDataCubeEngine.js';
|
|
41
41
|
import type { LegendDataCubeApplicationStore } from '../../LegendDataCubeBaseStore.js';
|
|
42
|
-
import type {
|
|
42
|
+
import type {
|
|
43
|
+
DataCubeAlertService,
|
|
44
|
+
DataCubeConfiguration,
|
|
45
|
+
} from '@finos/legend-data-cube';
|
|
43
46
|
|
|
44
47
|
export class LegendQueryDataCubeSourceBuilderState extends LegendDataCubeSourceBuilderState {
|
|
45
48
|
private readonly _engineServerClient: V1_EngineServerClient;
|
|
@@ -132,7 +135,7 @@ export class LegendQueryDataCubeSourceBuilderState extends LegendDataCubeSourceB
|
|
|
132
135
|
return Boolean(this.query);
|
|
133
136
|
}
|
|
134
137
|
|
|
135
|
-
override async
|
|
138
|
+
override async generateSourceData() {
|
|
136
139
|
if (!this.query) {
|
|
137
140
|
throw new IllegalStateError('Query is missing');
|
|
138
141
|
}
|
|
@@ -140,4 +143,10 @@ export class LegendQueryDataCubeSourceBuilderState extends LegendDataCubeSourceB
|
|
|
140
143
|
source.queryId = this.query.id;
|
|
141
144
|
return RawLegendQueryDataCubeSource.serialization.toJson(source);
|
|
142
145
|
}
|
|
146
|
+
|
|
147
|
+
override finalizeConfiguration(configuration: DataCubeConfiguration) {
|
|
148
|
+
if (this.query) {
|
|
149
|
+
configuration.name = this.query.name;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
143
152
|
}
|