@finos/legend-query-builder 4.16.6 → 4.16.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. package/lib/graph/QueryBuilderMetaModelConst.d.ts +1 -0
  2. package/lib/graph/QueryBuilderMetaModelConst.d.ts.map +1 -1
  3. package/lib/graph/QueryBuilderMetaModelConst.js +1 -0
  4. package/lib/graph/QueryBuilderMetaModelConst.js.map +1 -1
  5. package/lib/graph-manager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.js +5 -2
  6. package/lib/graph-manager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.js.map +1 -1
  7. package/lib/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.d.ts +3 -1
  8. package/lib/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.d.ts.map +1 -1
  9. package/lib/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.js +99 -2
  10. package/lib/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.js.map +1 -1
  11. package/lib/index.css +1 -1
  12. package/lib/package.json +5 -5
  13. package/lib/stores/QueryBuilderStateBuilder.d.ts.map +1 -1
  14. package/lib/stores/QueryBuilderStateBuilder.js +21 -2
  15. package/lib/stores/QueryBuilderStateBuilder.js.map +1 -1
  16. package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderRelationAggregationValueSpecBuilder.d.ts +19 -0
  17. package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderRelationAggregationValueSpecBuilder.d.ts.map +1 -0
  18. package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderRelationAggregationValueSpecBuilder.js +98 -0
  19. package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderRelationAggregationValueSpecBuilder.js.map +1 -0
  20. package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderTypedAggregationStateBuilder.d.ts +21 -0
  21. package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderTypedAggregationStateBuilder.d.ts.map +1 -0
  22. package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderTypedAggregationStateBuilder.js +102 -0
  23. package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderTypedAggregationStateBuilder.js.map +1 -0
  24. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.d.ts.map +1 -1
  25. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js +9 -3
  26. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js.map +1 -1
  27. package/lib/stores/fetch-structure/tds/projection/{QueryBuilderRelationProjectValueSpecBuidler.d.ts → QueryBuilderRelationProjectValueSpecBuilder.d.ts} +1 -1
  28. package/lib/stores/fetch-structure/tds/projection/{QueryBuilderRelationProjectValueSpecBuidler.d.ts.map → QueryBuilderRelationProjectValueSpecBuilder.d.ts.map} +1 -1
  29. package/lib/stores/fetch-structure/tds/projection/{QueryBuilderRelationProjectValueSpecBuidler.js → QueryBuilderRelationProjectValueSpecBuilder.js} +1 -1
  30. package/lib/stores/fetch-structure/tds/projection/{QueryBuilderRelationProjectValueSpecBuidler.js.map → QueryBuilderRelationProjectValueSpecBuilder.js.map} +1 -1
  31. package/lib/stores/fetch-structure/tds/projection/QueryBuilderTypedProjectionStateBuilder.d.ts.map +1 -1
  32. package/lib/stores/fetch-structure/tds/projection/QueryBuilderTypedProjectionStateBuilder.js +8 -9
  33. package/lib/stores/fetch-structure/tds/projection/QueryBuilderTypedProjectionStateBuilder.js.map +1 -1
  34. package/package.json +15 -15
  35. package/src/graph/QueryBuilderMetaModelConst.ts +1 -0
  36. package/src/graph-manager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.ts +4 -4
  37. package/src/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.ts +223 -2
  38. package/src/stores/QueryBuilderStateBuilder.ts +40 -8
  39. package/src/stores/fetch-structure/tds/aggregation/QueryBuilderRelationAggregationValueSpecBuilder.ts +196 -0
  40. package/src/stores/fetch-structure/tds/aggregation/QueryBuilderTypedAggregationStateBuilder.ts +253 -0
  41. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.ts +11 -3
  42. package/src/stores/fetch-structure/tds/projection/QueryBuilderTypedProjectionStateBuilder.ts +8 -9
  43. package/tsconfig.json +3 -1
  44. /package/src/stores/fetch-structure/tds/projection/{QueryBuilderRelationProjectValueSpecBuidler.ts → QueryBuilderRelationProjectValueSpecBuilder.ts} +0 -0
@@ -30,7 +30,7 @@ import {
30
30
  type V1_ProcessingContext,
31
31
  type ValueSpecification,
32
32
  type Type,
33
- type SimpleFunctionExpression,
33
+ SimpleFunctionExpression,
34
34
  V1_ValueSpecification,
35
35
  V1_buildBaseSimpleFunctionExpression,
36
36
  V1_buildGenericFunctionExpression,
@@ -997,7 +997,7 @@ export const V1_buildProjectFunctionExpression = (
997
997
  return expression;
998
998
  };
999
999
 
1000
- export const V1_buildGroupByFunctionExpression = (
1000
+ export const V1_buildTDSGroupByFunctionExpression = (
1001
1001
  functionName: string,
1002
1002
  parameters: V1_ValueSpecification[],
1003
1003
  openVariables: string[],
@@ -1140,6 +1140,227 @@ export const V1_buildGroupByFunctionExpression = (
1140
1140
  return expression;
1141
1141
  };
1142
1142
 
1143
+ export const V1_buildTypedGroupByFunctionExpression = (
1144
+ functionName: string,
1145
+ parameters: V1_ValueSpecification[],
1146
+ openVariables: string[],
1147
+ compileContext: V1_GraphBuilderContext,
1148
+ processingContext: V1_ProcessingContext,
1149
+ ): SimpleFunctionExpression => {
1150
+ assertTrue(
1151
+ parameters.length === 3,
1152
+ `Can't build relation groupBy() expression: groupBy() expects 2 arguments`,
1153
+ );
1154
+
1155
+ const precedingExpression = (
1156
+ parameters[0] as V1_ValueSpecification
1157
+ ).accept_ValueSpecificationVisitor(
1158
+ new V1_ValueSpecificationBuilder(
1159
+ compileContext,
1160
+ processingContext,
1161
+ openVariables,
1162
+ ),
1163
+ );
1164
+ assertNonNullable(
1165
+ precedingExpression.genericType,
1166
+ `Can't build relation groupBy() expression: preceding expression return type is missing`,
1167
+ );
1168
+
1169
+ // Assert that preceding function is a project() function
1170
+ const projectFunction = guaranteeType(
1171
+ precedingExpression,
1172
+ SimpleFunctionExpression,
1173
+ );
1174
+ if (
1175
+ projectFunction.functionName !==
1176
+ extractElementNameFromPath(
1177
+ QUERY_BUILDER_SUPPORTED_FUNCTIONS.RELATION_PROJECT,
1178
+ )
1179
+ ) {
1180
+ throw new UnsupportedOperationError(
1181
+ `Can't build relation groupBy() expression: preceding expression must be project() column expression`,
1182
+ );
1183
+ }
1184
+
1185
+ // Get normal (grouped) columns
1186
+ const columnsClassInstance = parameters[1];
1187
+ assertType(
1188
+ columnsClassInstance,
1189
+ V1_ClassInstance,
1190
+ `Can't build relation groupBy() expression: groupBy() expects argument #1 to be a ClassInstance`,
1191
+ );
1192
+ const columnExpressions = guaranteeType(
1193
+ columnsClassInstance.value,
1194
+ V1_ColSpecArray,
1195
+ `Can't build relation groupBy() expression: groupBy() expects argument #1 to hold col spec array instance value`,
1196
+ );
1197
+
1198
+ // Get aggregation columns
1199
+ const aggregationColumnsClassInstance = parameters[2];
1200
+ assertType(
1201
+ aggregationColumnsClassInstance,
1202
+ V1_ClassInstance,
1203
+ `Can't build groupBy() expression: groupBy() expects argument #2 to be a ClassInstance`,
1204
+ );
1205
+ const aggregationExpressions = guaranteeType(
1206
+ aggregationColumnsClassInstance.value,
1207
+ V1_ColSpecArray,
1208
+ `Can't build relation groupBy() expression: groupBy() expects argument #2 to hold col spec array instance value`,
1209
+ );
1210
+
1211
+ // Make sure top-level lambdas have their lambda parameter types set properly
1212
+ const topLevelLambdaParameters: V1_Variable[] =
1213
+ aggregationExpressions.colSpecs
1214
+ .map((colSpec) => [colSpec.function1, colSpec.function2])
1215
+ .flat()
1216
+ .filter(isNonNullable)
1217
+ .map((value) => value.parameters)
1218
+ .flat();
1219
+ topLevelLambdaParameters.forEach((variable) => {
1220
+ if (!variable.genericType) {
1221
+ const variableExpression = new VariableExpression(
1222
+ variable.name,
1223
+ precedingExpression.multiplicity,
1224
+ );
1225
+ variableExpression.genericType = precedingExpression.genericType;
1226
+ processingContext.addInferredVariables(variable.name, variableExpression);
1227
+ }
1228
+ });
1229
+
1230
+ const projectRelationReturnType = guaranteeType(
1231
+ projectFunction.genericType?.value.typeArguments?.[0]?.value.rawType,
1232
+ RelationType,
1233
+ `Can't build relation groupBy() expression: project() function does not return a relation`,
1234
+ );
1235
+
1236
+ // build column expressions
1237
+ const processedColumnExpressions = new ColSpecArrayInstance(Multiplicity.ONE);
1238
+ const processedColSpecArray = new ColSpecArray();
1239
+ processedColumnExpressions.values = [processedColSpecArray];
1240
+ const relationType = new RelationType(RelationType.ID);
1241
+ processedColSpecArray.colSpecs = columnExpressions.colSpecs.map((colSpec) => {
1242
+ const pColSpec = new ColSpec();
1243
+ pColSpec.name = colSpec.name;
1244
+
1245
+ // Add the column using the return type of the preceding project
1246
+ const column = projectRelationReturnType.columns.find(
1247
+ (_column) => _column.name === colSpec.name,
1248
+ );
1249
+ if (column) {
1250
+ relationType.columns.push(column);
1251
+ }
1252
+ return pColSpec;
1253
+ });
1254
+
1255
+ // build aggregation column expressions
1256
+ const processedAggregationExpressions = new ColSpecArrayInstance(
1257
+ Multiplicity.ONE,
1258
+ );
1259
+ const processedAggregationColSpecArray = new ColSpecArray();
1260
+ processedAggregationExpressions.values = [processedAggregationColSpecArray];
1261
+ processedAggregationColSpecArray.colSpecs =
1262
+ aggregationExpressions.colSpecs.map((colSpec) => {
1263
+ const pColSpec = new ColSpec();
1264
+ pColSpec.name = colSpec.name;
1265
+
1266
+ // Build the map lambda
1267
+ const mapFunction = guaranteeType(
1268
+ colSpec.function1,
1269
+ V1_Lambda,
1270
+ `Can't build relation col spec() expression: expects function1 to be a lambda`,
1271
+ );
1272
+ const mapLambda: ValueSpecification = buildProjectionColumnLambda(
1273
+ mapFunction,
1274
+ openVariables,
1275
+ compileContext,
1276
+ processingContext,
1277
+ );
1278
+ pColSpec.function1 = mapLambda;
1279
+
1280
+ // Build the reduce lambda
1281
+ const reduceFunction = guaranteeType(
1282
+ colSpec.function2,
1283
+ V1_Lambda,
1284
+ `Can't build relation col spec() expression: expects function2 to be a lambda`,
1285
+ );
1286
+ const reduceLambda = guaranteeType(
1287
+ reduceFunction.accept_ValueSpecificationVisitor(
1288
+ new V1_ValueSpecificationBuilder(
1289
+ compileContext,
1290
+ processingContext,
1291
+ openVariables,
1292
+ ),
1293
+ ),
1294
+ LambdaFunctionInstanceValue,
1295
+ `Can't build relation col spec() expression: expected aggregation function to be a lambda`,
1296
+ );
1297
+ pColSpec.function2 = reduceLambda;
1298
+
1299
+ // For now, we temporarily set the return type of the column in the groupBy() expression to be
1300
+ // the same as the return type of the column in the preceding project() expression.
1301
+ // The actual return type for the groupBy() expression will be determined when we process/build the graph.
1302
+ const returnType = projectRelationReturnType.columns.find(
1303
+ (_column) => _column.name === colSpec.name,
1304
+ )?.type;
1305
+ if (returnType) {
1306
+ relationType.columns.push(new RelationColumn(colSpec.name, returnType));
1307
+ } else {
1308
+ throw new UnsupportedOperationError(
1309
+ `Unable to find projected column with name ${colSpec.name}`,
1310
+ );
1311
+ }
1312
+
1313
+ return pColSpec;
1314
+ });
1315
+
1316
+ const expression = V1_buildBaseSimpleFunctionExpression(
1317
+ [
1318
+ precedingExpression,
1319
+ processedColumnExpressions,
1320
+ processedAggregationExpressions,
1321
+ ],
1322
+ functionName,
1323
+ compileContext,
1324
+ );
1325
+ const relationGenericType = new GenericType(Relation.INSTANCE);
1326
+ const relationTypeGenericType = new GenericType(relationType);
1327
+ relationGenericType.typeArguments = [
1328
+ GenericTypeExplicitReference.create(relationTypeGenericType),
1329
+ ];
1330
+ expression.genericType =
1331
+ GenericTypeExplicitReference.create(relationGenericType);
1332
+
1333
+ return expression;
1334
+ };
1335
+
1336
+ export const V1_buildGroupByFunctionExpression = (
1337
+ functionName: string,
1338
+ parameters: V1_ValueSpecification[],
1339
+ openVariables: string[],
1340
+ compileContext: V1_GraphBuilderContext,
1341
+ processingContext: V1_ProcessingContext,
1342
+ ): SimpleFunctionExpression => {
1343
+ if (
1344
+ functionName === QUERY_BUILDER_SUPPORTED_FUNCTIONS.RELATION_GROUP_BY ||
1345
+ parameters.length === 3
1346
+ ) {
1347
+ return V1_buildTypedGroupByFunctionExpression(
1348
+ functionName,
1349
+ parameters,
1350
+ openVariables,
1351
+ compileContext,
1352
+ processingContext,
1353
+ );
1354
+ }
1355
+ return V1_buildTDSGroupByFunctionExpression(
1356
+ functionName,
1357
+ parameters,
1358
+ openVariables,
1359
+ compileContext,
1360
+ processingContext,
1361
+ );
1362
+ };
1363
+
1143
1364
  export const V1_buildWatermarkFunctionExpression = (
1144
1365
  functionName: string,
1145
1366
  parameters: V1_ValueSpecification[],
@@ -101,6 +101,11 @@ import {
101
101
  isTypedProjectionExpression,
102
102
  processTypedTDSProjectExpression,
103
103
  } from './fetch-structure/tds/projection/QueryBuilderTypedProjectionStateBuilder.js';
104
+ import {
105
+ isTypedGroupByExpression,
106
+ processTypedAggregationColSpec,
107
+ processTypedGroupByExpression,
108
+ } from './fetch-structure/tds/aggregation/QueryBuilderTypedAggregationStateBuilder.js';
104
109
 
105
110
  const processGetAllExpression = (
106
111
  expression: SimpleFunctionExpression,
@@ -740,16 +745,24 @@ export class QueryBuilderValueSpecificationProcessor
740
745
  );
741
746
  return;
742
747
  } else if (
743
- matchFunctionName(
744
- functionName,
748
+ matchFunctionName(functionName, [
745
749
  QUERY_BUILDER_SUPPORTED_FUNCTIONS.TDS_GROUP_BY,
746
- )
750
+ QUERY_BUILDER_SUPPORTED_FUNCTIONS.RELATION_GROUP_BY,
751
+ ])
747
752
  ) {
748
- processTDSGroupByExpression(
749
- valueSpecification,
750
- this.queryBuilderState,
751
- this.parentLambda,
752
- );
753
+ if (isTypedGroupByExpression(valueSpecification)) {
754
+ processTypedGroupByExpression(
755
+ valueSpecification,
756
+ this.queryBuilderState,
757
+ this.parentLambda,
758
+ );
759
+ } else {
760
+ processTDSGroupByExpression(
761
+ valueSpecification,
762
+ this.queryBuilderState,
763
+ this.parentLambda,
764
+ );
765
+ }
753
766
  return;
754
767
  } else if (
755
768
  matchFunctionName(functionName, QUERY_BUILDER_SUPPORTED_FUNCTIONS.TDS_AGG)
@@ -1002,6 +1015,25 @@ export class QueryBuilderValueSpecificationProcessor
1002
1015
  }
1003
1016
  });
1004
1017
 
1018
+ return;
1019
+ } else if (
1020
+ matchFunctionName(this.parentExpression.functionName, [
1021
+ QUERY_BUILDER_SUPPORTED_FUNCTIONS.RELATION_GROUP_BY,
1022
+ ])
1023
+ ) {
1024
+ const spec = valueSpecification.values;
1025
+ assertTrue(
1026
+ spec.length === 1,
1027
+ `Can't process col spec array instance: value expected to be of size 1`,
1028
+ );
1029
+ guaranteeNonNullable(spec[0]).colSpecs.forEach((col) => {
1030
+ processTypedAggregationColSpec(
1031
+ col,
1032
+ this.parentExpression,
1033
+ this.queryBuilderState,
1034
+ );
1035
+ });
1036
+
1005
1037
  return;
1006
1038
  }
1007
1039
  throw new UnsupportedOperationError(
@@ -0,0 +1,196 @@
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
+ ColSpecArray,
19
+ type ValueSpecification,
20
+ extractElementNameFromPath,
21
+ SimpleFunctionExpression,
22
+ ColSpecArrayInstance,
23
+ Multiplicity,
24
+ ColSpec,
25
+ GenericType,
26
+ GenericTypeExplicitReference,
27
+ Relation,
28
+ RelationColumn,
29
+ RelationType,
30
+ LambdaFunctionInstanceValue,
31
+ AbstractPropertyExpression,
32
+ PropertyExplicitReference,
33
+ Property,
34
+ VariableExpression,
35
+ } from '@finos/legend-graph';
36
+ import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '../../../../graph/QueryBuilderMetaModelConst.js';
37
+ import type { QueryBuilderTDSState } from '../QueryBuilderTDSState.js';
38
+ import { buildGenericLambdaFunctionInstanceValue } from '../../../QueryBuilderValueSpecificationHelper.js';
39
+ import {
40
+ guaranteeNonNullable,
41
+ guaranteeType,
42
+ UnsupportedOperationError,
43
+ } from '@finos/legend-shared';
44
+ import { DEFAULT_LAMBDA_VARIABLE_NAME } from '@finos/legend-data-cube';
45
+
46
+ export const buildRelationAggregation = (
47
+ precedingExpression: ValueSpecification,
48
+ tdsState: QueryBuilderTDSState,
49
+ ): SimpleFunctionExpression => {
50
+ // Verify that preceding expression is a relation project
51
+ const projectFunction = guaranteeType(
52
+ precedingExpression,
53
+ SimpleFunctionExpression,
54
+ );
55
+ if (
56
+ projectFunction.functionName !==
57
+ extractElementNameFromPath(
58
+ QUERY_BUILDER_SUPPORTED_FUNCTIONS.RELATION_PROJECT,
59
+ )
60
+ ) {
61
+ throw new UnsupportedOperationError(
62
+ `Can't build relation groupBy() expression: previous expression must be project() column expression`,
63
+ );
64
+ }
65
+
66
+ // Build groupBy() expression
67
+ const groupByFunction = new SimpleFunctionExpression(
68
+ extractElementNameFromPath(
69
+ QUERY_BUILDER_SUPPORTED_FUNCTIONS.RELATION_GROUP_BY,
70
+ ),
71
+ );
72
+ const queryBuilderState = tdsState.queryBuilderState;
73
+
74
+ // Build normal (grouped) columns
75
+ const groupByCols = new ColSpecArrayInstance(Multiplicity.ONE, undefined);
76
+ const groupByColSpecArray = new ColSpecArray();
77
+ groupByCols.values = [groupByColSpecArray];
78
+
79
+ // Build aggregation columns
80
+ const aggregationCols = new ColSpecArrayInstance(Multiplicity.ONE, undefined);
81
+ const aggregationColSpecArray = new ColSpecArray();
82
+ aggregationCols.values = [aggregationColSpecArray];
83
+
84
+ // Build relation return type
85
+ const relationType = new RelationType(RelationType.ID);
86
+
87
+ // Add normal (non-aggregated) columns to groupByCols
88
+ tdsState.projectionColumns
89
+ .filter(
90
+ (projectionColumnState) =>
91
+ !tdsState.aggregationState.columns.some(
92
+ (aggregationColumnState) =>
93
+ aggregationColumnState.projectionColumnState ===
94
+ projectionColumnState,
95
+ ),
96
+ )
97
+ .forEach((projectionColumnState) => {
98
+ // Create and add column to groupByColSpecArray
99
+ const colSpec = new ColSpec();
100
+ colSpec.name = projectionColumnState.columnName;
101
+ groupByColSpecArray.colSpecs.push(colSpec);
102
+
103
+ // Add column return type to relationType
104
+ const returnType = guaranteeNonNullable(
105
+ projectionColumnState.getColumnType(),
106
+ `Can't create value spec for projection column ${projectionColumnState.columnName}. Missing type.`,
107
+ );
108
+ relationType.columns.push(
109
+ new RelationColumn(projectionColumnState.columnName, returnType),
110
+ );
111
+ });
112
+
113
+ // Add aggregation columns to aggregationCols
114
+ tdsState.aggregationState.columns.forEach((aggregationColumnState) => {
115
+ // Create and add column to aggregationColSpecArray
116
+ const colSpec = new ColSpec();
117
+ colSpec.name = aggregationColumnState.columnName;
118
+ aggregationColSpecArray.colSpecs.push(colSpec);
119
+
120
+ // Build map function (function1)
121
+ // First, get the ColSpec from the preceding projection so we can get the name of the projected column.
122
+ const projectionColSpec = guaranteeNonNullable(
123
+ guaranteeNonNullable(
124
+ (projectFunction.parametersValues[1] as ColSpecArrayInstance).values[0],
125
+ 'Could not find ColSpec array in project() function first parameter',
126
+ ).colSpecs.find(
127
+ (_colSpec) => _colSpec.name === aggregationColumnState.columnName,
128
+ ),
129
+ `Could not find projected column matching aggregation column '${aggregationColumnState.columnName}'`,
130
+ );
131
+ const projectedPropertyExpression = guaranteeType(
132
+ guaranteeType(projectionColSpec.function1, LambdaFunctionInstanceValue)
133
+ .values[0]?.expressionSequence[0],
134
+ AbstractPropertyExpression,
135
+ );
136
+ const projectedProperty = guaranteeType(
137
+ projectedPropertyExpression.func.value,
138
+ Property,
139
+ );
140
+ // Second, build a new AbstractPropertyExpression for our map function
141
+ const newPropertyExpression = new AbstractPropertyExpression('');
142
+ newPropertyExpression.func = PropertyExplicitReference.create(
143
+ new Property(
144
+ projectionColSpec.name,
145
+ projectedProperty.multiplicity,
146
+ projectedProperty.genericType,
147
+ projectedProperty._OWNER,
148
+ ),
149
+ );
150
+ newPropertyExpression.parametersValues = [
151
+ new VariableExpression(DEFAULT_LAMBDA_VARIABLE_NAME, Multiplicity.ONE),
152
+ ];
153
+ const mapLambda = buildGenericLambdaFunctionInstanceValue(
154
+ DEFAULT_LAMBDA_VARIABLE_NAME,
155
+ [newPropertyExpression],
156
+ queryBuilderState.graphManagerState.graph,
157
+ );
158
+ colSpec.function1 = mapLambda;
159
+
160
+ // Reduce function (function2)
161
+ const reduceLambda = buildGenericLambdaFunctionInstanceValue(
162
+ aggregationColumnState.lambdaParameterName,
163
+ [
164
+ aggregationColumnState.operator.buildAggregateExpressionFromState(
165
+ aggregationColumnState,
166
+ ),
167
+ ],
168
+ aggregationColumnState.aggregationState.tdsState.queryBuilderState
169
+ .graphManagerState.graph,
170
+ );
171
+ colSpec.function2 = reduceLambda;
172
+
173
+ // Add column return type to relationType
174
+ const returnType = guaranteeNonNullable(
175
+ aggregationColumnState.getColumnType(),
176
+ `Can't create value spec for aggregation column ${aggregationColumnState.columnName}. Missing type.`,
177
+ );
178
+ relationType.columns.push(
179
+ new RelationColumn(aggregationColumnState.columnName, returnType),
180
+ );
181
+ });
182
+
183
+ groupByFunction.parametersValues = [
184
+ precedingExpression,
185
+ groupByCols,
186
+ aggregationCols,
187
+ ];
188
+ const relationGenericType = new GenericType(Relation.INSTANCE);
189
+ const relationTypeGenericType = new GenericType(relationType);
190
+ relationGenericType.typeArguments = [
191
+ GenericTypeExplicitReference.create(relationTypeGenericType),
192
+ ];
193
+ groupByFunction.genericType =
194
+ GenericTypeExplicitReference.create(relationGenericType);
195
+ return groupByFunction;
196
+ };