@finos/legend-application-data-cube 0.3.14 → 0.3.15

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 (97) hide show
  1. package/lib/application/Core_LegendDataCube_LegendApplicationPlugin.d.ts +7 -1
  2. package/lib/application/Core_LegendDataCube_LegendApplicationPlugin.d.ts.map +1 -1
  3. package/lib/application/Core_LegendDataCube_LegendApplicationPlugin.js +10 -1
  4. package/lib/application/Core_LegendDataCube_LegendApplicationPlugin.js.map +1 -1
  5. package/lib/application/LegendDataCube.d.ts.map +1 -1
  6. package/lib/application/LegendDataCube.js +2 -0
  7. package/lib/application/LegendDataCube.js.map +1 -1
  8. package/lib/application/LegendDataCubeApplicationPlugin.d.ts +9 -0
  9. package/lib/application/LegendDataCubeApplicationPlugin.d.ts.map +1 -1
  10. package/lib/application/LegendDataCubeApplicationPlugin.js.map +1 -1
  11. package/lib/components/__test-utils__/LegendDataCubeStoreTestUtils.d.ts.map +1 -1
  12. package/lib/components/__test-utils__/LegendDataCubeStoreTestUtils.js +2 -0
  13. package/lib/components/__test-utils__/LegendDataCubeStoreTestUtils.js.map +1 -1
  14. package/lib/components/builder/LegendDataCubeBuilder.d.ts.map +1 -1
  15. package/lib/components/builder/LegendDataCubeBuilder.js +10 -2
  16. package/lib/components/builder/LegendDataCubeBuilder.js.map +1 -1
  17. package/lib/components/builder/LegendDataCubeCreator.js +4 -4
  18. package/lib/components/builder/LegendDataCubeCreator.js.map +1 -1
  19. package/lib/components/builder/LegendDataCubeSourceViewer.d.ts.map +1 -1
  20. package/lib/components/builder/LegendDataCubeSourceViewer.js +134 -18
  21. package/lib/components/builder/LegendDataCubeSourceViewer.js.map +1 -1
  22. package/lib/components/builder/source/{AdhocQueryDataCubeSourceBuilder.d.ts → FreeformTDSExpressionDataCubeSourceBuilder.d.ts} +4 -4
  23. package/lib/components/builder/source/FreeformTDSExpressionDataCubeSourceBuilder.d.ts.map +1 -0
  24. package/lib/components/builder/source/{AdhocQueryDataCubeSourceBuilder.js → FreeformTDSExpressionDataCubeSourceBuilder.js} +2 -2
  25. package/lib/components/builder/source/FreeformTDSExpressionDataCubeSourceBuilder.js.map +1 -0
  26. package/lib/components/builder/source/LegendQueryDataCubeSourceBuilder.d.ts.map +1 -1
  27. package/lib/components/builder/source/LegendQueryDataCubeSourceBuilder.js +30 -4
  28. package/lib/components/builder/source/LegendQueryDataCubeSourceBuilder.js.map +1 -1
  29. package/lib/components/builder/source/LegendQueryDataCubeSourceBuilder_DataCubeApplicationPlugin.d.ts +24 -0
  30. package/lib/components/builder/source/LegendQueryDataCubeSourceBuilder_DataCubeApplicationPlugin.d.ts.map +1 -0
  31. package/lib/components/builder/source/LegendQueryDataCubeSourceBuilder_DataCubeApplicationPlugin.js +67 -0
  32. package/lib/components/builder/source/LegendQueryDataCubeSourceBuilder_DataCubeApplicationPlugin.js.map +1 -0
  33. package/lib/index.css +2 -2
  34. package/lib/index.css.map +1 -1
  35. package/lib/package.json +3 -2
  36. package/lib/stores/LegendDataCubeDataCubeEngine.d.ts +6 -1
  37. package/lib/stores/LegendDataCubeDataCubeEngine.d.ts.map +1 -1
  38. package/lib/stores/LegendDataCubeDataCubeEngine.js +78 -50
  39. package/lib/stores/LegendDataCubeDataCubeEngine.js.map +1 -1
  40. package/lib/stores/builder/LegendDataCubeBuilderStore.d.ts +2 -1
  41. package/lib/stores/builder/LegendDataCubeBuilderStore.d.ts.map +1 -1
  42. package/lib/stores/builder/LegendDataCubeBuilderStore.js +4 -2
  43. package/lib/stores/builder/LegendDataCubeBuilderStore.js.map +1 -1
  44. package/lib/stores/builder/LegendDataCubeCreatorState.d.ts.map +1 -1
  45. package/lib/stores/builder/LegendDataCubeCreatorState.js +5 -5
  46. package/lib/stores/builder/LegendDataCubeCreatorState.js.map +1 -1
  47. package/lib/stores/builder/source/{AdHocCodeEditorState.d.ts → FreeformExpressionCodeEditorState.d.ts} +2 -2
  48. package/lib/stores/builder/source/FreeformExpressionCodeEditorState.d.ts.map +1 -0
  49. package/lib/stores/builder/source/{AdHocCodeEditorState.js → FreeformExpressionCodeEditorState.js} +2 -2
  50. package/lib/stores/builder/source/FreeformExpressionCodeEditorState.js.map +1 -0
  51. package/lib/stores/builder/source/{AdhocQueryDataCubeSourceBuilderState.d.ts → FreeformTDSExpressionDataCubeSourceBuilderState.d.ts} +4 -4
  52. package/lib/stores/builder/source/FreeformTDSExpressionDataCubeSourceBuilderState.d.ts.map +1 -0
  53. package/lib/stores/builder/source/{AdhocQueryDataCubeSourceBuilderState.js → FreeformTDSExpressionDataCubeSourceBuilderState.js} +8 -8
  54. package/lib/stores/builder/source/FreeformTDSExpressionDataCubeSourceBuilderState.js.map +1 -0
  55. package/lib/stores/builder/source/LegendDataCubeSourceBuilderState.d.ts +1 -1
  56. package/lib/stores/builder/source/LegendDataCubeSourceBuilderState.d.ts.map +1 -1
  57. package/lib/stores/builder/source/LegendDataCubeSourceBuilderState.js +1 -1
  58. package/lib/stores/builder/source/LegendDataCubeSourceBuilderState.js.map +1 -1
  59. package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderState.d.ts +21 -3
  60. package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderState.d.ts.map +1 -1
  61. package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderState.js +73 -7
  62. package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderState.js.map +1 -1
  63. package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderStateHelper.d.ts +20 -0
  64. package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderStateHelper.d.ts.map +1 -0
  65. package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderStateHelper.js +33 -0
  66. package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderStateHelper.js.map +1 -0
  67. package/lib/stores/model/LegendQueryDataCubeSource.d.ts +6 -3
  68. package/lib/stores/model/LegendQueryDataCubeSource.d.ts.map +1 -1
  69. package/lib/stores/model/LegendQueryDataCubeSource.js +3 -2
  70. package/lib/stores/model/LegendQueryDataCubeSource.js.map +1 -1
  71. package/package.json +12 -11
  72. package/src/application/Core_LegendDataCube_LegendApplicationPlugin.ts +21 -2
  73. package/src/application/LegendDataCube.tsx +2 -0
  74. package/src/application/LegendDataCubeApplicationPlugin.ts +15 -0
  75. package/src/components/__test-utils__/LegendDataCubeStoreTestUtils.tsx +2 -0
  76. package/src/components/builder/LegendDataCubeBuilder.tsx +34 -20
  77. package/src/components/builder/LegendDataCubeCreator.tsx +5 -5
  78. package/src/components/builder/LegendDataCubeSourceViewer.tsx +426 -78
  79. package/src/components/builder/source/{AdhocQueryDataCubeSourceBuilder.tsx → FreeformTDSExpressionDataCubeSourceBuilder.tsx} +3 -3
  80. package/src/components/builder/source/LegendQueryDataCubeSourceBuilder.tsx +92 -1
  81. package/src/components/builder/source/LegendQueryDataCubeSourceBuilder_DataCubeApplicationPlugin.tsx +128 -0
  82. package/src/stores/LegendDataCubeDataCubeEngine.ts +133 -75
  83. package/src/stores/builder/LegendDataCubeBuilderStore.tsx +4 -1
  84. package/src/stores/builder/LegendDataCubeCreatorState.tsx +7 -4
  85. package/src/stores/builder/source/{AdHocCodeEditorState.tsx → FreeformExpressionCodeEditorState.tsx} +1 -1
  86. package/src/stores/builder/source/{AdhocQueryDataCubeSourceBuilderState.ts → FreeformTDSExpressionDataCubeSourceBuilderState.ts} +8 -8
  87. package/src/stores/builder/source/LegendDataCubeSourceBuilderState.ts +1 -1
  88. package/src/stores/builder/source/LegendQueryDataCubeSourceBuilderState.ts +161 -8
  89. package/src/stores/builder/source/LegendQueryDataCubeSourceBuilderStateHelper.ts +67 -0
  90. package/src/stores/model/LegendQueryDataCubeSource.ts +8 -4
  91. package/tsconfig.json +5 -3
  92. package/lib/components/builder/source/AdhocQueryDataCubeSourceBuilder.d.ts.map +0 -1
  93. package/lib/components/builder/source/AdhocQueryDataCubeSourceBuilder.js.map +0 -1
  94. package/lib/stores/builder/source/AdHocCodeEditorState.d.ts.map +0 -1
  95. package/lib/stores/builder/source/AdHocCodeEditorState.js.map +0 -1
  96. package/lib/stores/builder/source/AdhocQueryDataCubeSourceBuilderState.d.ts.map +0 -1
  97. package/lib/stores/builder/source/AdhocQueryDataCubeSourceBuilderState.js.map +0 -1
@@ -0,0 +1,128 @@
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 { guaranteeType } from '@finos/legend-shared';
18
+ import packageJson from '../../../../package.json' with { type: 'json' };
19
+ import { LegendDataCubeApplicationPlugin } from '../../../application/LegendDataCubeApplicationPlugin.js';
20
+ import type { LegendDataCubeBuilderState } from '../../../stores/builder/LegendDataCubeBuilderStore.js';
21
+ import { LegendQueryDataCubeSource } from '../../../stores/model/LegendQueryDataCubeSource.js';
22
+ import { V1_AppliedFunction, V1_ValueSpecification } from '@finos/legend-graph';
23
+ import { clsx } from '@finos/legend-art';
24
+ import type {
25
+ ApplicationStore,
26
+ LegendApplicationConfig,
27
+ LegendApplicationPluginManager,
28
+ LegendApplicationPlugin,
29
+ } from '@finos/legend-application';
30
+ import {
31
+ buildDatePickerOption,
32
+ getV1_ValueSpecificationStringValue,
33
+ } from '@finos/legend-query-builder';
34
+
35
+ const getNameOfV1ValueSpecification = (
36
+ value: V1_ValueSpecification,
37
+ applicationStore: ApplicationStore<
38
+ LegendApplicationConfig,
39
+ LegendApplicationPluginManager<LegendApplicationPlugin>
40
+ >,
41
+ ): string | undefined => {
42
+ if (value instanceof V1_AppliedFunction) {
43
+ const possibleDateLabel = buildDatePickerOption(
44
+ value,
45
+ applicationStore,
46
+ ).label;
47
+ if (possibleDateLabel) {
48
+ return possibleDateLabel;
49
+ }
50
+ }
51
+ return getV1_ValueSpecificationStringValue(value, applicationStore);
52
+ };
53
+
54
+ export class LegendQueryDataCubeSourceBuilder_DataCubeApplicationPlugin extends LegendDataCubeApplicationPlugin {
55
+ static NAME = packageJson.extensions.legendQueryDataCubeSourceBuilderPlugin;
56
+
57
+ constructor() {
58
+ super(
59
+ LegendQueryDataCubeSourceBuilder_DataCubeApplicationPlugin.NAME,
60
+ packageJson.version,
61
+ );
62
+ }
63
+
64
+ override getSourceViewerHeight(
65
+ builder: LegendDataCubeBuilderState | undefined,
66
+ ): number | undefined {
67
+ if (builder?.source instanceof LegendQueryDataCubeSource) {
68
+ return (
69
+ 200 +
70
+ 20 * builder.source.parameterValues.length +
71
+ (builder.dataCube?.isCachingEnabled() ? 70 : 0)
72
+ );
73
+ }
74
+ return undefined;
75
+ }
76
+
77
+ override builderInnerHeaderRenderer(
78
+ builder: LegendDataCubeBuilderState | undefined,
79
+ ): React.ReactNode | null {
80
+ if (
81
+ builder?.source instanceof LegendQueryDataCubeSource &&
82
+ builder.source.parameterValues.length
83
+ ) {
84
+ const source = guaranteeType(builder.source, LegendQueryDataCubeSource);
85
+
86
+ return (
87
+ <div
88
+ key={LegendQueryDataCubeSourceBuilder_DataCubeApplicationPlugin.NAME}
89
+ className="flex h-full flex-auto items-center overflow-auto border-l border-neutral-300 pl-2"
90
+ >
91
+ Parameters:
92
+ {source.parameterValues.map((param) => {
93
+ const paramValue = getNameOfV1ValueSpecification(
94
+ guaranteeType(param.valueSpec, V1_ValueSpecification),
95
+ builder._store.application,
96
+ );
97
+ return (
98
+ <div
99
+ key={param.variable.name}
100
+ className="max-w-200 ml-2 flex cursor-pointer hover:brightness-95"
101
+ onClick={() => {
102
+ // Set sourceViewerDisplay height based on length of parameters.
103
+ // Height should also be increased if we need to show the parameter
104
+ // editing disabled message.
105
+ builder._store.sourceViewerDisplay.configuration.window.height =
106
+ Math.min(600, this.getSourceViewerHeight(builder) ?? 200);
107
+ builder._store.sourceViewerDisplay.open();
108
+ }}
109
+ >
110
+ <span className="truncate bg-neutral-300 px-1">
111
+ {param.variable.name}
112
+ </span>
113
+ <span
114
+ className={clsx('truncate bg-neutral-200 px-1', {
115
+ 'text-neutral-500': paramValue === '',
116
+ })}
117
+ >
118
+ {paramValue === '' ? '(empty)' : paramValue}
119
+ </span>
120
+ </div>
121
+ );
122
+ })}
123
+ </div>
124
+ );
125
+ }
126
+ return null;
127
+ }
128
+ }
@@ -42,7 +42,6 @@ import {
42
42
  V1_buildEngineError,
43
43
  V1_EngineError,
44
44
  V1_PackageableType,
45
- V1_deserializeRawValueSpecificationType,
46
45
  V1_Protocol,
47
46
  type V1_ExecutionPlan,
48
47
  V1_deserializeExecutionPlan,
@@ -85,6 +84,8 @@ import {
85
84
  LET_TOKEN,
86
85
  V1_AppliedFunction,
87
86
  type V1_LambdaReturnTypeResult,
87
+ V1_Variable,
88
+ type QueryInfo,
88
89
  } from '@finos/legend-graph';
89
90
  import {
90
91
  _elementPtr,
@@ -92,20 +93,21 @@ import {
92
93
  type CompletionItem,
93
94
  _function,
94
95
  DataCubeFunction,
95
- AdhocQueryDataCubeSource,
96
- ADHOC_QUERY_DATA_CUBE_SOURCE_TYPE,
97
- RawAdhocQueryDataCubeSource,
96
+ FreeformTDSExpressionDataCubeSource,
97
+ FREEFORM_TDS_EXPRESSION_DATA_CUBE_SOURCE_TYPE,
98
+ RawFreeformTDSExpressionDataCubeSource,
98
99
  _lambda,
99
- _defaultPrimitiveTypeValue,
100
100
  CachedDataCubeSource,
101
101
  type DataCubeExecutionOptions,
102
102
  type DataCubeCacheInitializationOptions,
103
103
  DataCubeExecutionError,
104
104
  RawUserDefinedFunctionDataCubeSource,
105
- ADHOC_FUNCTION_DATA_CUBE_SOURCE_TYPE,
105
+ USER_FUNCTION_DATA_CUBE_SOURCE_TYPE,
106
106
  type DataCubeSource,
107
107
  UserDefinedFunctionDataCubeSource,
108
108
  DataCubeQueryFilterOperator,
109
+ _primitiveValue,
110
+ _defaultPrimitiveTypeValue,
109
111
  } from '@finos/legend-data-cube';
110
112
  import {
111
113
  isNonNullable,
@@ -211,7 +213,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
211
213
  path: source.functionPath,
212
214
  runtime: source.runtime,
213
215
  },
214
- sourceType: ADHOC_FUNCTION_DATA_CUBE_SOURCE_TYPE,
216
+ sourceType: USER_FUNCTION_DATA_CUBE_SOURCE_TYPE,
215
217
  };
216
218
  } else if (source instanceof LocalFileDataCubeSource) {
217
219
  const deserializedModel = V1_deserializePureModelContext(source.model);
@@ -240,7 +242,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
240
242
  },
241
243
  sourceType: LOCAL_FILE_QUERY_DATA_CUBE_SOURCE_TYPE,
242
244
  };
243
- } else if (source instanceof AdhocQueryDataCubeSource) {
245
+ } else if (source instanceof FreeformTDSExpressionDataCubeSource) {
244
246
  const deserializedModel = V1_deserializePureModelContext(source.model);
245
247
 
246
248
  const sdlcInfo =
@@ -262,7 +264,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
262
264
  mapping: source.mapping,
263
265
  runtime: source.runtime,
264
266
  },
265
- sourceType: ADHOC_QUERY_DATA_CUBE_SOURCE_TYPE,
267
+ sourceType: FREEFORM_TDS_EXPRESSION_DATA_CUBE_SOURCE_TYPE,
266
268
  };
267
269
  }
268
270
  return {};
@@ -283,7 +285,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
283
285
  },
284
286
  sourceType: source._type,
285
287
  };
286
- } else if (source._type === ADHOC_FUNCTION_DATA_CUBE_SOURCE_TYPE) {
288
+ } else if (source._type === USER_FUNCTION_DATA_CUBE_SOURCE_TYPE) {
287
289
  const rawSource =
288
290
  RawUserDefinedFunctionDataCubeSource.serialization.fromJson(source);
289
291
  const deserializedModel = V1_deserializePureModelContext(rawSource.model);
@@ -320,9 +322,9 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
320
322
  },
321
323
  sourceType: source._type,
322
324
  };
323
- } else if (source._type === ADHOC_QUERY_DATA_CUBE_SOURCE_TYPE) {
325
+ } else if (source._type === FREEFORM_TDS_EXPRESSION_DATA_CUBE_SOURCE_TYPE) {
324
326
  const rawSource =
325
- RawAdhocQueryDataCubeSource.serialization.fromJson(source);
327
+ RawFreeformTDSExpressionDataCubeSource.serialization.fromJson(source);
326
328
  const deserializedModel = V1_deserializePureModelContext(rawSource.model);
327
329
 
328
330
  const sdlcInfo =
@@ -362,10 +364,10 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
362
364
 
363
365
  override async processSource(value: PlainObject): Promise<DataCubeSource> {
364
366
  switch (value._type) {
365
- case ADHOC_QUERY_DATA_CUBE_SOURCE_TYPE: {
367
+ case FREEFORM_TDS_EXPRESSION_DATA_CUBE_SOURCE_TYPE: {
366
368
  const rawSource =
367
- RawAdhocQueryDataCubeSource.serialization.fromJson(value);
368
- const source = new AdhocQueryDataCubeSource();
369
+ RawFreeformTDSExpressionDataCubeSource.serialization.fromJson(value);
370
+ const source = new FreeformTDSExpressionDataCubeSource();
369
371
  if (rawSource.mapping) {
370
372
  source.mapping = rawSource.mapping;
371
373
  }
@@ -499,7 +501,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
499
501
  }
500
502
  return source;
501
503
  }
502
- case ADHOC_FUNCTION_DATA_CUBE_SOURCE_TYPE: {
504
+ case USER_FUNCTION_DATA_CUBE_SOURCE_TYPE: {
503
505
  const rawSource =
504
506
  RawUserDefinedFunctionDataCubeSource.serialization.fromJson(value);
505
507
  const deserializedModel = V1_deserializePureModelContext(
@@ -644,58 +646,10 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
644
646
  );
645
647
  }
646
648
 
647
- // To handle parameter value with function calls we
648
- // 1. Separate the parameters with function calls from regular parameters
649
- // 2. Add let statements for function parameter values and store them in the source's letParameterValueSpec
650
- // 3. Prepend the let statements to the lambda body when we execute the query
651
- const letFuncs: V1_ValueSpecification[] = [];
652
- const parameterValues = (
653
- await Promise.all(
654
- source.lambda.parameters.map(async (parameter) => {
655
- if (
656
- parameter.genericType?.rawType instanceof V1_PackageableType
657
- ) {
658
- const type = parameter.genericType.rawType.fullPath;
659
- const defaultValueString =
660
- queryInfo.defaultParameterValues?.find(
661
- (val) => val.name === parameter.name,
662
- )?.content;
663
- const defaultValueSpec =
664
- defaultValueString !== undefined
665
- ? await this.parseValueSpecification(defaultValueString)
666
- : {
667
- _type: V1_deserializeRawValueSpecificationType(type),
668
- value: _defaultPrimitiveTypeValue(type),
669
- };
670
- if (defaultValueSpec instanceof V1_AppliedFunction) {
671
- const letFunc = guaranteeType(
672
- this.deserializeValueSpecification(
673
- await this._engineServerClient.grammarToJSON_lambda(
674
- `${LET_TOKEN} ${parameter.name} ${DataCubeQueryFilterOperator.EQUAL} ${defaultValueString}`,
675
- '',
676
- undefined,
677
- undefined,
678
- false,
679
- ),
680
- ),
681
- V1_Lambda,
682
- );
683
- letFuncs.push(...letFunc.body);
684
- } else {
685
- const paramValue = new V1_ParameterValue();
686
- paramValue.name = parameter.name;
687
- paramValue.value = defaultValueSpec;
688
- return paramValue;
689
- }
690
- }
691
- return undefined;
692
- }),
693
- )
694
- ).filter(isNonNullable);
695
- source.letParameterValueSpec = letFuncs;
696
- source.parameterValues = parameterValues;
697
- source.lambda.parameters = source.lambda.parameters.filter((param) =>
698
- parameterValues.find((p) => p.name === param.name),
649
+ source.parameterValues = await this._getQueryParameterValues(
650
+ rawSource,
651
+ source.lambda,
652
+ queryInfo,
699
653
  );
700
654
  return source;
701
655
  }
@@ -758,7 +712,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
758
712
  codeBlock = codeBlock.startsWith(LAMBDA_PIPE)
759
713
  ? codeBlock.substring(LAMBDA_PIPE.length)
760
714
  : codeBlock;
761
- if (context instanceof AdhocQueryDataCubeSource) {
715
+ if (context instanceof FreeformTDSExpressionDataCubeSource) {
762
716
  return (
763
717
  await this._engineServerClient.completeCode({
764
718
  codeBlock,
@@ -868,17 +822,54 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
868
822
  const startTime = performance.now();
869
823
 
870
824
  try {
871
- if (source instanceof AdhocQueryDataCubeSource) {
825
+ if (source instanceof FreeformTDSExpressionDataCubeSource) {
872
826
  result = await this._runQuery(query, source.model, undefined, options);
873
827
  } else if (source instanceof UserDefinedFunctionDataCubeSource) {
874
828
  result = await this._runQuery(query, source.model, undefined, options);
875
829
  } else if (source instanceof LegendQueryDataCubeSource) {
876
- query.parameters = source.lambda.parameters;
830
+ // To handle parameter value with function calls we
831
+ // 1. Separate the parameters with function calls from regular parameters
832
+ // 2. Add let statements for function parameter values and store them in the source's letParameterValueSpec
833
+ // 3. Prepend the let statements to the lambda body when we execute the query
834
+ const letFuncs: V1_ValueSpecification[] = [];
835
+ const filteredParameterValues = (
836
+ await Promise.all(
837
+ source.parameterValues.map(async ({ variable, valueSpec }) => {
838
+ if (variable.genericType?.rawType instanceof V1_PackageableType) {
839
+ if (valueSpec instanceof V1_AppliedFunction) {
840
+ const letFunc = guaranteeType(
841
+ this.deserializeValueSpecification(
842
+ await this._engineServerClient.grammarToJSON_lambda(
843
+ `${LET_TOKEN} ${variable.name} ${DataCubeQueryFilterOperator.EQUAL} ${await this.getValueSpecificationCode(valueSpec)}`,
844
+ '',
845
+ undefined,
846
+ undefined,
847
+ false,
848
+ ),
849
+ ),
850
+ V1_Lambda,
851
+ );
852
+ letFuncs.push(...letFunc.body);
853
+ } else {
854
+ const paramValue = new V1_ParameterValue();
855
+ paramValue.name = variable.name;
856
+ paramValue.value = valueSpec;
857
+ return paramValue;
858
+ }
859
+ }
860
+ return undefined;
861
+ }),
862
+ )
863
+ ).filter(isNonNullable);
864
+
865
+ query.parameters = source.lambda.parameters.filter((param) =>
866
+ filteredParameterValues.find((p) => p.name === param.name),
867
+ );
877
868
  // If the source lambda has multiple expressions, we should prepend all but the
878
869
  // last expression to the transformed query body (which came from the final
879
870
  // expression of the source lambda).
880
871
  query.body = [
881
- ...source.letParameterValueSpec,
872
+ ...letFuncs,
882
873
  ...(source.lambda.body.length > 1
883
874
  ? source.lambda.body.slice(0, -1)
884
875
  : []),
@@ -887,7 +878,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
887
878
  result = await this._runQuery(
888
879
  query,
889
880
  source.model,
890
- source.parameterValues,
881
+ filteredParameterValues,
891
882
  options,
892
883
  );
893
884
  } else if (source instanceof CachedDataCubeSource) {
@@ -979,7 +970,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
979
970
  }
980
971
 
981
972
  override buildExecutionContext(source: DataCubeSource) {
982
- if (source instanceof AdhocQueryDataCubeSource) {
973
+ if (source instanceof FreeformTDSExpressionDataCubeSource) {
983
974
  return _function(
984
975
  DataCubeFunction.FROM,
985
976
  [
@@ -1107,7 +1098,7 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
1107
1098
  query: PlainObject<V1_Lambda>,
1108
1099
  source: DataCubeSource,
1109
1100
  ) {
1110
- if (source instanceof AdhocQueryDataCubeSource) {
1101
+ if (source instanceof FreeformTDSExpressionDataCubeSource) {
1111
1102
  return this._getLambdaRelationType(query, source.model);
1112
1103
  } else if (source instanceof UserDefinedFunctionDataCubeSource) {
1113
1104
  return this._getLambdaRelationType(query, source.model);
@@ -1154,6 +1145,73 @@ export class LegendDataCubeDataCubeEngine extends DataCubeEngine {
1154
1145
  };
1155
1146
  }
1156
1147
 
1148
+ async _getQueryParameterValues(
1149
+ rawSource: RawLegendQueryDataCubeSource,
1150
+ lambda: V1_Lambda,
1151
+ queryInfo: QueryInfo,
1152
+ ): Promise<{ variable: V1_Variable; valueSpec: V1_ValueSpecification }[]> {
1153
+ const rawSourceParameters: {
1154
+ variable: V1_Variable;
1155
+ valueSpec: V1_ValueSpecification;
1156
+ }[] =
1157
+ rawSource.parameterValues?.map(([variable, _value]) => ({
1158
+ variable: guaranteeType(
1159
+ V1_deserializeValueSpecification(JSON.parse(variable), []),
1160
+ V1_Variable,
1161
+ ),
1162
+ valueSpec: V1_deserializeValueSpecification(JSON.parse(_value), []),
1163
+ })) ?? [];
1164
+
1165
+ const lambdaParameterValues: {
1166
+ variable: V1_Variable;
1167
+ valueSpec: V1_ValueSpecification;
1168
+ }[] = (
1169
+ await Promise.all(
1170
+ lambda.parameters.map(async (parameter) => {
1171
+ if (parameter.genericType?.rawType instanceof V1_PackageableType) {
1172
+ const type = parameter.genericType.rawType.fullPath;
1173
+ const defaultValueString = queryInfo.defaultParameterValues?.find(
1174
+ (val) => val.name === parameter.name,
1175
+ )?.content;
1176
+ const defaultValueSpec =
1177
+ defaultValueString !== undefined
1178
+ ? await this.parseValueSpecification(defaultValueString)
1179
+ : _primitiveValue(type, _defaultPrimitiveTypeValue(type));
1180
+ return { variable: parameter, valueSpec: defaultValueSpec };
1181
+ }
1182
+ return undefined;
1183
+ }),
1184
+ )
1185
+ ).filter(isNonNullable);
1186
+
1187
+ // Here, we need to handle 3 cases:
1188
+ // 1. The query has a parameter with the same name and type as the raw source (which comes from the PersistentDataCube).
1189
+ // In this case, we use the parameter value from the raw source.
1190
+ // 2. The query has a parameter that does not exist in the raw source (i.e., the parameter was renamed, the type was changed,
1191
+ // or was newly added after the DataCube was last saved). In this case, we use the default value from the query.
1192
+ // 3. The raw source has a parameter that does not exist in the query. In this case, we discard the parameter as it
1193
+ // is no longer used in the query.
1194
+ return lambdaParameterValues.map(({ variable, valueSpec }) => {
1195
+ const rawSourceParameter = rawSourceParameters.find(
1196
+ ({ variable: _rawVariable, valueSpec: _rawValueSpec }) =>
1197
+ _rawVariable.name === variable.name,
1198
+ );
1199
+ const rawSourceVariable = rawSourceParameter?.variable;
1200
+ const rawSourceValueSpec = rawSourceParameter?.valueSpec;
1201
+ if (
1202
+ rawSourceVariable &&
1203
+ rawSourceValueSpec &&
1204
+ rawSourceVariable.genericType?.rawType instanceof V1_PackageableType &&
1205
+ variable.genericType?.rawType instanceof V1_PackageableType &&
1206
+ rawSourceVariable.genericType.rawType.fullPath ===
1207
+ variable.genericType.rawType.fullPath
1208
+ ) {
1209
+ return { variable: rawSourceVariable, valueSpec: rawSourceValueSpec };
1210
+ }
1211
+ return { variable, valueSpec };
1212
+ });
1213
+ }
1214
+
1157
1215
  private async _runQuery(
1158
1216
  query: V1_Lambda,
1159
1217
  model: PlainObject<V1_PureModelContext>,
@@ -74,6 +74,7 @@ export class LegendDataCubeBuilderState {
74
74
  readonly uuid = uuid();
75
75
  readonly startTime = Date.now();
76
76
 
77
+ readonly _store!: LegendDataCubeBuilderStore;
77
78
  readonly initialSpecification!: DataCubeSpecification;
78
79
  persistentDataCube?: PersistentDataCube | undefined;
79
80
 
@@ -81,6 +82,7 @@ export class LegendDataCubeBuilderState {
81
82
  source?: DataCubeSource | undefined;
82
83
 
83
84
  constructor(
85
+ store: LegendDataCubeBuilderStore,
84
86
  specification: DataCubeSpecification,
85
87
  persistentDataCube?: PersistentDataCube | undefined,
86
88
  ) {
@@ -95,6 +97,7 @@ export class LegendDataCubeBuilderState {
95
97
  setSource: action,
96
98
  });
97
99
 
100
+ this._store = store;
98
101
  this.initialSpecification = specification;
99
102
  this.persistentDataCube = persistentDataCube;
100
103
  }
@@ -423,7 +426,7 @@ export class LegendDataCubeBuilderStore {
423
426
  dataCubeId: string,
424
427
  ) {
425
428
  this.setBuilder(
426
- new LegendDataCubeBuilderState(specification, persistentDataCube),
429
+ new LegendDataCubeBuilderState(this, specification, persistentDataCube),
427
430
  );
428
431
  this.updateWindowTitle(persistentDataCube);
429
432
 
@@ -35,7 +35,7 @@ import {
35
35
  } from '@finos/legend-data-cube';
36
36
  import type { LegendDataCubeDataCubeEngine } from '../LegendDataCubeDataCubeEngine.js';
37
37
  import { LegendDataCubeCreator } from '../../components/builder/LegendDataCubeCreator.js';
38
- import { AdhocQueryDataCubeSourceBuilderState } from './source/AdhocQueryDataCubeSourceBuilderState.js';
38
+ import { FreeformTDSExpressionDataCubeSourceBuilderState } from './source/FreeformTDSExpressionDataCubeSourceBuilderState.js';
39
39
  import {
40
40
  LegendDataCubeBuilderState,
41
41
  type LegendDataCubeBuilderStore,
@@ -100,11 +100,12 @@ export class LegendDataCubeCreatorState {
100
100
  this._application,
101
101
  this._engine,
102
102
  this._store.engineServerClient,
103
+ this._store.depotServerClient,
103
104
  this._store.graphManager,
104
105
  this._alertService,
105
106
  );
106
- case LegendDataCubeSourceBuilderType.ADHOC_QUERY:
107
- return new AdhocQueryDataCubeSourceBuilderState(
107
+ case LegendDataCubeSourceBuilderType.FREEFORM_TDS_EXPRESSION:
108
+ return new FreeformTDSExpressionDataCubeSourceBuilderState(
108
109
  this._application,
109
110
  this._engine,
110
111
  this._alertService,
@@ -152,7 +153,9 @@ export class LegendDataCubeCreatorState {
152
153
  }
153
154
 
154
155
  // reset
155
- this._store.setBuilder(new LegendDataCubeBuilderState(specification));
156
+ this._store.setBuilder(
157
+ new LegendDataCubeBuilderState(this._store, specification),
158
+ );
156
159
  // only update the route instead of reloading in case we are creating
157
160
  // a new DataCube when we are editing another DataCube
158
161
  this._application.navigationService.navigator.updateCurrentLocation(
@@ -28,7 +28,7 @@ import {
28
28
  } from '@finos/legend-shared';
29
29
  import { action, makeObservable, observable, runInAction } from 'mobx';
30
30
 
31
- export class AdHocCodeEditorState extends DataCubeCodeEditorState {
31
+ export class FreeformExpressionCodeEditorState extends DataCubeCodeEditorState {
32
32
  protected override readonly uuid = uuid();
33
33
  codeSuffix: string;
34
34
 
@@ -41,11 +41,11 @@ import {
41
41
  import {
42
42
  _lambda,
43
43
  type DataCubeAlertService,
44
- RawAdhocQueryDataCubeSource,
44
+ RawFreeformTDSExpressionDataCubeSource,
45
45
  } from '@finos/legend-data-cube';
46
- import { AdHocCodeEditorState } from './AdHocCodeEditorState.js';
46
+ import { FreeformExpressionCodeEditorState } from './FreeformExpressionCodeEditorState.js';
47
47
 
48
- export class AdhocQueryDataCubeSourceBuilderState extends LegendDataCubeSourceBuilderState {
48
+ export class FreeformTDSExpressionDataCubeSourceBuilderState extends LegendDataCubeSourceBuilderState {
49
49
  builderStore: LegendDataCubeBuilderStore;
50
50
  projects: StoreProjectData[] = [];
51
51
  currentProject?: StoreProjectData | undefined;
@@ -57,7 +57,7 @@ export class AdhocQueryDataCubeSourceBuilderState extends LegendDataCubeSourceBu
57
57
  currentMapping?: V1_Mapping | undefined;
58
58
  modelPointer: PlainObject<V1_PureModelContextPointer> | undefined;
59
59
 
60
- codeEditorState: AdHocCodeEditorState;
60
+ codeEditorState: FreeformExpressionCodeEditorState;
61
61
  queryCompileState = ActionState.create();
62
62
  code = '';
63
63
 
@@ -92,7 +92,7 @@ export class AdhocQueryDataCubeSourceBuilderState extends LegendDataCubeSourceBu
92
92
  });
93
93
 
94
94
  this.modelPointer = this.buildPureModelContextPointer();
95
- this.codeEditorState = new AdHocCodeEditorState(
95
+ this.codeEditorState = new FreeformExpressionCodeEditorState(
96
96
  application.alertUnhandledError,
97
97
  this.modelPointer,
98
98
  this.compileQueryCallback,
@@ -157,7 +157,7 @@ export class AdhocQueryDataCubeSourceBuilderState extends LegendDataCubeSourceBu
157
157
  }
158
158
 
159
159
  override get label(): LegendDataCubeSourceBuilderType {
160
- return LegendDataCubeSourceBuilderType.ADHOC_QUERY;
160
+ return LegendDataCubeSourceBuilderType.FREEFORM_TDS_EXPRESSION;
161
161
  }
162
162
 
163
163
  override get isValid(): boolean {
@@ -231,7 +231,7 @@ export class AdhocQueryDataCubeSourceBuilderState extends LegendDataCubeSourceBu
231
231
  );
232
232
  }
233
233
 
234
- const source = new RawAdhocQueryDataCubeSource();
234
+ const source = new RawFreeformTDSExpressionDataCubeSource();
235
235
  if (this.currentMapping) {
236
236
  source.mapping = this.currentMapping.path;
237
237
  }
@@ -247,6 +247,6 @@ export class AdhocQueryDataCubeSourceBuilderState extends LegendDataCubeSourceBu
247
247
  );
248
248
  }
249
249
  }
250
- return RawAdhocQueryDataCubeSource.serialization.toJson(source);
250
+ return RawFreeformTDSExpressionDataCubeSource.serialization.toJson(source);
251
251
  }
252
252
  }
@@ -24,7 +24,7 @@ import type {
24
24
 
25
25
  export enum LegendDataCubeSourceBuilderType {
26
26
  LEGEND_QUERY = 'Legend Query',
27
- ADHOC_QUERY = 'Ad hoc Query',
27
+ FREEFORM_TDS_EXPRESSION = 'Freeform TDS Expression',
28
28
  LOCAL_FILE = 'Local File',
29
29
  USER_DEFINED_FUNCTION = 'User Defined Function',
30
30
  }