@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.
- package/lib/graph/QueryBuilderMetaModelConst.d.ts +1 -0
- package/lib/graph/QueryBuilderMetaModelConst.d.ts.map +1 -1
- package/lib/graph/QueryBuilderMetaModelConst.js +1 -0
- package/lib/graph/QueryBuilderMetaModelConst.js.map +1 -1
- package/lib/graph-manager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.js +5 -2
- package/lib/graph-manager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.d.ts +3 -1
- package/lib/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.js +99 -2
- package/lib/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.js.map +1 -1
- package/lib/index.css +1 -1
- package/lib/package.json +5 -5
- package/lib/stores/QueryBuilderStateBuilder.d.ts.map +1 -1
- package/lib/stores/QueryBuilderStateBuilder.js +21 -2
- package/lib/stores/QueryBuilderStateBuilder.js.map +1 -1
- package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderRelationAggregationValueSpecBuilder.d.ts +19 -0
- package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderRelationAggregationValueSpecBuilder.d.ts.map +1 -0
- package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderRelationAggregationValueSpecBuilder.js +98 -0
- package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderRelationAggregationValueSpecBuilder.js.map +1 -0
- package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderTypedAggregationStateBuilder.d.ts +21 -0
- package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderTypedAggregationStateBuilder.d.ts.map +1 -0
- package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderTypedAggregationStateBuilder.js +102 -0
- package/lib/stores/fetch-structure/tds/aggregation/QueryBuilderTypedAggregationStateBuilder.js.map +1 -0
- package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.d.ts.map +1 -1
- package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js +9 -3
- package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js.map +1 -1
- package/lib/stores/fetch-structure/tds/projection/{QueryBuilderRelationProjectValueSpecBuidler.d.ts → QueryBuilderRelationProjectValueSpecBuilder.d.ts} +1 -1
- package/lib/stores/fetch-structure/tds/projection/{QueryBuilderRelationProjectValueSpecBuidler.d.ts.map → QueryBuilderRelationProjectValueSpecBuilder.d.ts.map} +1 -1
- package/lib/stores/fetch-structure/tds/projection/{QueryBuilderRelationProjectValueSpecBuidler.js → QueryBuilderRelationProjectValueSpecBuilder.js} +1 -1
- package/lib/stores/fetch-structure/tds/projection/{QueryBuilderRelationProjectValueSpecBuidler.js.map → QueryBuilderRelationProjectValueSpecBuilder.js.map} +1 -1
- package/lib/stores/fetch-structure/tds/projection/QueryBuilderTypedProjectionStateBuilder.d.ts.map +1 -1
- package/lib/stores/fetch-structure/tds/projection/QueryBuilderTypedProjectionStateBuilder.js +8 -9
- package/lib/stores/fetch-structure/tds/projection/QueryBuilderTypedProjectionStateBuilder.js.map +1 -1
- package/package.json +15 -15
- package/src/graph/QueryBuilderMetaModelConst.ts +1 -0
- package/src/graph-manager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.ts +4 -4
- package/src/graph-manager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.ts +223 -2
- package/src/stores/QueryBuilderStateBuilder.ts +40 -8
- package/src/stores/fetch-structure/tds/aggregation/QueryBuilderRelationAggregationValueSpecBuilder.ts +196 -0
- package/src/stores/fetch-structure/tds/aggregation/QueryBuilderTypedAggregationStateBuilder.ts +253 -0
- package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.ts +11 -3
- package/src/stores/fetch-structure/tds/projection/QueryBuilderTypedProjectionStateBuilder.ts +8 -9
- package/tsconfig.json +3 -1
- /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
|
-
|
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
|
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
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
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
|
+
};
|