@cubejs-backend/schema-compiler 1.3.11 → 1.3.13
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/dist/src/adapter/BaseDimension.d.ts +3 -3
- package/dist/src/adapter/BaseDimension.d.ts.map +1 -1
- package/dist/src/adapter/BaseDimension.js.map +1 -1
- package/dist/src/adapter/BaseFilter.d.ts +5 -1
- package/dist/src/adapter/BaseFilter.d.ts.map +1 -1
- package/dist/src/adapter/BaseFilter.js +13 -3
- package/dist/src/adapter/BaseFilter.js.map +1 -1
- package/dist/src/adapter/BaseGroupFilter.d.ts +2 -2
- package/dist/src/adapter/BaseGroupFilter.d.ts.map +1 -1
- package/dist/src/adapter/BaseGroupFilter.js.map +1 -1
- package/dist/src/adapter/BaseMeasure.d.ts +4 -4
- package/dist/src/adapter/BaseMeasure.js.map +1 -1
- package/dist/src/adapter/BaseQuery.d.ts +119 -35
- package/dist/src/adapter/BaseQuery.d.ts.map +1 -1
- package/dist/src/adapter/BaseQuery.js +226 -43
- package/dist/src/adapter/BaseQuery.js.map +1 -1
- package/dist/src/adapter/BaseSegment.d.ts +2 -2
- package/dist/src/adapter/BaseSegment.js.map +1 -1
- package/dist/src/adapter/BaseTimeDimension.d.ts +1 -1
- package/dist/src/adapter/CubeStoreQuery.d.ts +6 -6
- package/dist/src/adapter/CubeStoreQuery.d.ts.map +1 -1
- package/dist/src/adapter/CubeStoreQuery.js +3 -4
- package/dist/src/adapter/CubeStoreQuery.js.map +1 -1
- package/dist/src/adapter/HiveQuery.d.ts +7 -2
- package/dist/src/adapter/HiveQuery.d.ts.map +1 -1
- package/dist/src/adapter/HiveQuery.js +2 -2
- package/dist/src/adapter/HiveQuery.js.map +1 -1
- package/dist/src/adapter/PreAggregations.d.ts +130 -209
- package/dist/src/adapter/PreAggregations.d.ts.map +1 -1
- package/dist/src/adapter/PreAggregations.js +205 -148
- package/dist/src/adapter/PreAggregations.js.map +1 -1
- package/dist/src/compiler/CubeEvaluator.d.ts +37 -9
- package/dist/src/compiler/CubeEvaluator.d.ts.map +1 -1
- package/dist/src/compiler/CubeEvaluator.js +13 -2
- package/dist/src/compiler/CubeEvaluator.js.map +1 -1
- package/dist/src/compiler/CubeSymbols.d.ts +1 -1
- package/dist/src/compiler/CubeSymbols.d.ts.map +1 -1
- package/dist/src/compiler/CubeSymbols.js.map +1 -1
- package/dist/src/compiler/CubeValidator.d.ts.map +1 -1
- package/dist/src/compiler/CubeValidator.js +16 -7
- package/dist/src/compiler/CubeValidator.js.map +1 -1
- package/package.json +6 -6
|
@@ -5,15 +5,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.PreAggregations = void 0;
|
|
7
7
|
const ramda_1 = __importDefault(require("ramda"));
|
|
8
|
-
const shared_1 = require("@cubejs-backend/shared");
|
|
9
8
|
const CubeSymbols_1 = require("../compiler/CubeSymbols");
|
|
10
9
|
const UserError_1 = require("../compiler/UserError");
|
|
10
|
+
const BaseMeasure_1 = require("./BaseMeasure");
|
|
11
11
|
class PreAggregations {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
query;
|
|
13
|
+
historyQueries;
|
|
14
|
+
cubeLatticeCache;
|
|
15
|
+
cubeLattices;
|
|
16
|
+
hasCumulativeMeasuresValue = false;
|
|
17
|
+
preAggregationForQuery = undefined;
|
|
17
18
|
constructor(query, historyQueries, cubeLatticeCache) {
|
|
18
19
|
this.query = query;
|
|
19
20
|
this.historyQueries = historyQueries;
|
|
@@ -21,7 +22,7 @@ class PreAggregations {
|
|
|
21
22
|
this.cubeLattices = {};
|
|
22
23
|
}
|
|
23
24
|
/**
|
|
24
|
-
*
|
|
25
|
+
* It returns full pre-aggregation object (with keyQueries, previewSql, loadSql, and so on.
|
|
25
26
|
*/
|
|
26
27
|
preAggregationsDescription() {
|
|
27
28
|
const preAggregations = [this.preAggregationsDescriptionLocal()].concat(this.query.subQueryDimensions.map(d => this.query.subQueryDescription(d).subQuery)
|
|
@@ -41,7 +42,7 @@ class PreAggregations {
|
|
|
41
42
|
return ramda_1.default.pipe(ramda_1.default.map(cube => {
|
|
42
43
|
const { preAggregations } = this.collectOriginalSqlPreAggregations(() => this.query.cubeSql(cube));
|
|
43
44
|
return ramda_1.default.unnest(preAggregations.map(p => this.preAggregationDescriptionsFor(p)));
|
|
44
|
-
}), ramda_1.default.filter(
|
|
45
|
+
}), ramda_1.default.filter((x) => Boolean(x)), ramda_1.default.unnest)(this.preAggregationCubes());
|
|
45
46
|
}
|
|
46
47
|
return [];
|
|
47
48
|
}
|
|
@@ -52,10 +53,10 @@ class PreAggregations {
|
|
|
52
53
|
preAggregationDescriptionsFor(foundPreAggregation) {
|
|
53
54
|
let preAggregations = [foundPreAggregation];
|
|
54
55
|
if (foundPreAggregation.preAggregation.type === 'rollupJoin') {
|
|
55
|
-
preAggregations = foundPreAggregation.preAggregationsToJoin;
|
|
56
|
+
preAggregations = foundPreAggregation.preAggregationsToJoin || [];
|
|
56
57
|
}
|
|
57
58
|
if (foundPreAggregation.preAggregation.type === 'rollupLambda') {
|
|
58
|
-
preAggregations = foundPreAggregation.referencedPreAggregations;
|
|
59
|
+
preAggregations = foundPreAggregation.referencedPreAggregations || [];
|
|
59
60
|
}
|
|
60
61
|
return preAggregations.map(preAggregation => {
|
|
61
62
|
if (this.canPartitionsBeUsed(preAggregation)) {
|
|
@@ -66,28 +67,29 @@ class PreAggregations {
|
|
|
66
67
|
}).reduce((a, b) => a.concat(b), []);
|
|
67
68
|
}
|
|
68
69
|
canPartitionsBeUsed(foundPreAggregation) {
|
|
69
|
-
return foundPreAggregation.preAggregation.partitionGranularity &&
|
|
70
|
-
foundPreAggregation.references.timeDimensions
|
|
71
|
-
foundPreAggregation.references.timeDimensions.length;
|
|
70
|
+
return !!foundPreAggregation.preAggregation.partitionGranularity &&
|
|
71
|
+
!!foundPreAggregation.references.timeDimensions?.length;
|
|
72
72
|
}
|
|
73
73
|
addPartitionRangeTo(foundPreAggregation, dimension, range, boundaryDateRange) {
|
|
74
|
-
return
|
|
75
|
-
|
|
74
|
+
return {
|
|
75
|
+
...foundPreAggregation,
|
|
76
|
+
preAggregation: {
|
|
77
|
+
...foundPreAggregation.preAggregation,
|
|
76
78
|
partitionTimeDimensions: [{
|
|
77
79
|
dimension,
|
|
78
80
|
dateRange: range,
|
|
79
81
|
boundaryDateRange
|
|
80
82
|
}],
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
83
85
|
}
|
|
84
86
|
partitionDimension(foundPreAggregation) {
|
|
85
87
|
const { dimension } = foundPreAggregation.references.timeDimensions[0];
|
|
86
88
|
const partitionDimension = this.query.newTimeDimension({
|
|
87
89
|
dimension,
|
|
88
90
|
granularity: this.castGranularity(foundPreAggregation.preAggregation.partitionGranularity),
|
|
89
|
-
dateRange: this.query.timeDimensions[0]
|
|
90
|
-
boundaryDateRange: this.query.timeDimensions[0]
|
|
91
|
+
dateRange: this.query.timeDimensions[0]?.dateRange,
|
|
92
|
+
boundaryDateRange: this.query.timeDimensions[0]?.boundaryDateRange
|
|
91
93
|
});
|
|
92
94
|
return { dimension, partitionDimension };
|
|
93
95
|
}
|
|
@@ -96,7 +98,7 @@ class PreAggregations {
|
|
|
96
98
|
const descriptions = query !== this.query ? query.preAggregations.preAggregationsDescription() : [];
|
|
97
99
|
return descriptions.concat(this.preAggregationDescriptionFor(cube, foundPreAggregation));
|
|
98
100
|
}
|
|
99
|
-
|
|
101
|
+
hasCumulativeMeasures() {
|
|
100
102
|
if (!this.hasCumulativeMeasuresValue) {
|
|
101
103
|
this.hasCumulativeMeasuresValue = PreAggregations.hasCumulativeMeasures(this.query);
|
|
102
104
|
}
|
|
@@ -128,10 +130,10 @@ class PreAggregations {
|
|
|
128
130
|
const tableName = this.preAggregationTableName(cube, preAggregationName, preAggregation);
|
|
129
131
|
const invalidateKeyQueries = this.query.preAggregationInvalidateKeyQueries(cube, preAggregation, preAggregationName);
|
|
130
132
|
const queryForSqlEvaluation = this.query.preAggregationQueryForSqlEvaluation(cube, preAggregation);
|
|
131
|
-
const partitionInvalidateKeyQueries = queryForSqlEvaluation.partitionInvalidateKeyQueries?.(cube, preAggregation);
|
|
132
133
|
const allBackAliasMembers = this.query.allBackAliasMembers();
|
|
133
|
-
|
|
134
|
-
|
|
134
|
+
let matchedTimeDimension;
|
|
135
|
+
if (preAggregation.partitionGranularity && !this.hasCumulativeMeasures()) {
|
|
136
|
+
matchedTimeDimension = this.query.timeDimensions.find(td => {
|
|
135
137
|
if (!td.dateRange) {
|
|
136
138
|
return false;
|
|
137
139
|
}
|
|
@@ -139,7 +141,6 @@ class PreAggregations {
|
|
|
139
141
|
foundPreAggregation.references.timeDimensions;
|
|
140
142
|
const timeDimensionReference = timeDimensionsReference[0];
|
|
141
143
|
// timeDimensionsReference[*].dimension can contain full join path, so we should trim it
|
|
142
|
-
// TODO check full join path match here
|
|
143
144
|
const timeDimensionReferenceDimension = CubeSymbols_1.CubeSymbols.joinHintFromPath(timeDimensionReference.dimension).path;
|
|
144
145
|
if (td.dimension === timeDimensionReferenceDimension) {
|
|
145
146
|
return true;
|
|
@@ -147,17 +148,21 @@ class PreAggregations {
|
|
|
147
148
|
// Handling for views
|
|
148
149
|
return td.dimension === allBackAliasMembers[timeDimensionReferenceDimension];
|
|
149
150
|
});
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
151
|
+
}
|
|
152
|
+
let filters;
|
|
153
|
+
if (preAggregation.partitionGranularity) {
|
|
154
|
+
filters = this.query.filters?.filter((td) => {
|
|
155
|
+
// TODO support all date operators
|
|
156
|
+
if (td.isDateOperator() && 'camelizeOperator' in td && td.camelizeOperator === 'inDateRange') {
|
|
157
|
+
if (td.dimension === foundPreAggregation.references.timeDimensions[0].dimension) {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
// Handling for views
|
|
161
|
+
return td.dimension === allBackAliasMembers[foundPreAggregation.references.timeDimensions[0].dimension];
|
|
155
162
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return false;
|
|
160
|
-
});
|
|
163
|
+
return false;
|
|
164
|
+
});
|
|
165
|
+
}
|
|
161
166
|
const uniqueKeyColumnsDefault = () => null;
|
|
162
167
|
const uniqueKeyColumns = ({
|
|
163
168
|
rollup: () => queryForSqlEvaluation.preAggregationUniqueKeyColumns(cube, preAggregation),
|
|
@@ -166,12 +171,11 @@ class PreAggregations {
|
|
|
166
171
|
const aggregationsColumns = this.aggregationsColumns(cube, preAggregation);
|
|
167
172
|
return {
|
|
168
173
|
preAggregationId: `${cube}.${preAggregationName}`,
|
|
169
|
-
timezone: this.query.options
|
|
174
|
+
timezone: this.query.options?.timezone,
|
|
170
175
|
timestampFormat: queryForSqlEvaluation.timestampFormat(),
|
|
171
176
|
timestampPrecision: queryForSqlEvaluation.timestampPrecision(),
|
|
172
177
|
tableName,
|
|
173
178
|
invalidateKeyQueries,
|
|
174
|
-
partitionInvalidateKeyQueries,
|
|
175
179
|
type: preAggregation.type,
|
|
176
180
|
external: preAggregation.external,
|
|
177
181
|
previewSql: queryForSqlEvaluation.preAggregationPreviewSql(tableName),
|
|
@@ -182,15 +186,17 @@ class PreAggregations {
|
|
|
182
186
|
uniqueKeyColumns,
|
|
183
187
|
aggregationsColumns,
|
|
184
188
|
dataSource: queryForSqlEvaluation.dataSource,
|
|
185
|
-
// in fact we can reference preAggregation.granularity however accessing timeDimensions is more strict and consistent
|
|
189
|
+
// in fact, we can reference preAggregation.granularity however accessing timeDimensions is more strict and consistent
|
|
186
190
|
granularity: references.timeDimensions[0]?.granularity,
|
|
187
191
|
partitionGranularity: preAggregation.partitionGranularity,
|
|
188
|
-
updateWindowSeconds: preAggregation.refreshKey &&
|
|
192
|
+
updateWindowSeconds: preAggregation.refreshKey &&
|
|
193
|
+
'updateWindow' in preAggregation.refreshKey &&
|
|
194
|
+
preAggregation.refreshKey?.updateWindow &&
|
|
189
195
|
queryForSqlEvaluation.parseSecondDuration(preAggregation.refreshKey.updateWindow),
|
|
190
196
|
preAggregationStartEndQueries: (preAggregation.partitionGranularity || references.timeDimensions[0]?.granularity) &&
|
|
191
197
|
this.refreshRangeQuery(cube).preAggregationStartEndQueries(cube, preAggregation),
|
|
192
|
-
matchedTimeDimensionDateRange: preAggregation.partitionGranularity && (matchedTimeDimension
|
|
193
|
-
filters
|
|
198
|
+
matchedTimeDimensionDateRange: preAggregation.partitionGranularity && (matchedTimeDimension?.boundaryDateRangeFormatted() ||
|
|
199
|
+
filters?.[0]?.formattedDateRange() // TODO intersect all date ranges
|
|
194
200
|
),
|
|
195
201
|
indexesSql: Object.keys(preAggregation.indexes || {})
|
|
196
202
|
.map(index => {
|
|
@@ -198,7 +204,7 @@ class PreAggregations {
|
|
|
198
204
|
const indexName = this.preAggregationTableName(cube, `${foundPreAggregation.sqlAlias || preAggregationName}_${index}`, preAggregation, true);
|
|
199
205
|
return {
|
|
200
206
|
indexName,
|
|
201
|
-
sql: queryForSqlEvaluation.indexSql(cube, preAggregation, preAggregation.indexes[index], indexName, tableName)
|
|
207
|
+
sql: queryForSqlEvaluation.indexSql(cube, preAggregation, preAggregation.indexes?.[index], indexName, tableName)
|
|
202
208
|
};
|
|
203
209
|
}),
|
|
204
210
|
createTableIndexes: Object.keys(preAggregation.indexes || {})
|
|
@@ -207,8 +213,8 @@ class PreAggregations {
|
|
|
207
213
|
const indexName = this.preAggregationTableName(cube, `${foundPreAggregation.sqlAlias || preAggregationName}_${index}`, preAggregation, true);
|
|
208
214
|
return {
|
|
209
215
|
indexName,
|
|
210
|
-
type: preAggregation.indexes[index].type,
|
|
211
|
-
columns: queryForSqlEvaluation.evaluateIndexColumns(cube, preAggregation.indexes[index])
|
|
216
|
+
type: preAggregation.indexes?.[index].type,
|
|
217
|
+
columns: queryForSqlEvaluation.evaluateIndexColumns(cube, preAggregation.indexes?.[index])
|
|
212
218
|
};
|
|
213
219
|
}),
|
|
214
220
|
readOnly: preAggregation.readOnly || queryForSqlEvaluation.preAggregationReadOnly(cube, preAggregation),
|
|
@@ -218,7 +224,7 @@ class PreAggregations {
|
|
|
218
224
|
lastRollupLambda: preAggregation.lastRollupLambda,
|
|
219
225
|
};
|
|
220
226
|
}
|
|
221
|
-
preAggregationTableName(cube, preAggregationName, preAggregation, skipSchema) {
|
|
227
|
+
preAggregationTableName(cube, preAggregationName, preAggregation, skipSchema = false) {
|
|
222
228
|
const name = preAggregation.sqlAlias || preAggregationName;
|
|
223
229
|
return this.query.preAggregationTableName(cube, name, skipSchema);
|
|
224
230
|
}
|
|
@@ -238,10 +244,10 @@ class PreAggregations {
|
|
|
238
244
|
}
|
|
239
245
|
static transformQueryToCanUseForm(query) {
|
|
240
246
|
const flattenDimensionMembers = this.flattenDimensionMembers(query);
|
|
241
|
-
const sortedDimensions = this.squashDimensions(
|
|
247
|
+
const sortedDimensions = this.squashDimensions(flattenDimensionMembers);
|
|
242
248
|
const allBackAliasMembers = query.allBackAliasMembers();
|
|
243
|
-
const measures = query.measures
|
|
244
|
-
const measurePaths = ramda_1.default.uniq(this.flattenMembers(measures).map(m => m.expressionPath()));
|
|
249
|
+
const measures = [...query.measures, ...query.measureFilters];
|
|
250
|
+
const measurePaths = ramda_1.default.uniq(this.flattenMembers(measures).filter((m) => m instanceof BaseMeasure_1.BaseMeasure).map(m => m.expressionPath()));
|
|
245
251
|
const collectLeafMeasures = query.collectLeafMeasures.bind(query);
|
|
246
252
|
const dimensionsList = query.dimensions.map(dim => dim.expressionPath());
|
|
247
253
|
const segmentsList = query.segments.map(s => s.expressionPath());
|
|
@@ -270,7 +276,7 @@ class PreAggregations {
|
|
|
270
276
|
sortedUsedCubePrimaryKeys.sort();
|
|
271
277
|
}
|
|
272
278
|
const measureToLeafMeasures = {};
|
|
273
|
-
const leafMeasurePaths = ramda_1.default.pipe(ramda_1.default.map(m => {
|
|
279
|
+
const leafMeasurePaths = ramda_1.default.pipe(ramda_1.default.map((m) => {
|
|
274
280
|
const leafMeasures = query.collectFrom([m], collectLeafMeasures, 'collectLeafMeasures');
|
|
275
281
|
measureToLeafMeasures[m.measure] = leafMeasures.map((measure) => {
|
|
276
282
|
const baseMeasure = query.newMeasure(measure);
|
|
@@ -297,7 +303,7 @@ class PreAggregations {
|
|
|
297
303
|
const ownedTimeDimensionsWithRollupGranularity = PreAggregations.sortTimeDimensionsWithRollupGranularity(ownedTimeDimensions);
|
|
298
304
|
const ownedTimeDimensionsAsIs = PreAggregations.timeDimensionsAsIs(ownedTimeDimensions);
|
|
299
305
|
const hasNoTimeDimensionsWithoutGranularity = !query.timeDimensions.filter(d => !d.granularity).length;
|
|
300
|
-
const allFiltersWithinSelectedDimensions = ramda_1.default.all(d => dimensionsList.indexOf(d) !== -1)(ramda_1.default.flatten(query.filters.map(f => f.getMembers())).map(f => query.cubeEvaluator.pathFromArray(f.path())));
|
|
306
|
+
const allFiltersWithinSelectedDimensions = ramda_1.default.all((d) => dimensionsList.indexOf(d) !== -1)(ramda_1.default.flatten(query.filters.map(f => f.getMembers())).map(f => query.cubeEvaluator.pathFromArray(f.path())));
|
|
301
307
|
const isAdditive = ramda_1.default.all(m => m.isAdditive(), query.measures);
|
|
302
308
|
const hasMultiStage = ramda_1.default.any(m => m.isMultiStage(), query.measures);
|
|
303
309
|
const leafMeasures = leafMeasurePaths.map(path => query.newMeasure(path));
|
|
@@ -339,23 +345,16 @@ class PreAggregations {
|
|
|
339
345
|
hasMultiStage
|
|
340
346
|
};
|
|
341
347
|
}
|
|
342
|
-
/**
|
|
343
|
-
*
|
|
344
|
-
* @param query
|
|
345
|
-
* @param members
|
|
346
|
-
* @param {Map<string, Array<string>>} cubeToJoinPrefix
|
|
347
|
-
* @returns {Array<string>}
|
|
348
|
-
*/
|
|
349
348
|
static ownedMembers(query, members) {
|
|
350
349
|
return ramda_1.default.pipe(ramda_1.default.uniq, ramda_1.default.sortBy(ramda_1.default.identity))(query
|
|
351
350
|
.collectFrom(members, query.collectMemberNamesFor.bind(query), 'collectMemberNamesFor')
|
|
352
351
|
.filter(d => query.cubeEvaluator.byPathAnyType(d).ownedByCube));
|
|
353
352
|
}
|
|
354
353
|
static sortTimeDimensionsWithRollupGranularity(timeDimensions) {
|
|
355
|
-
return timeDimensions && ramda_1.default.sortBy(
|
|
354
|
+
return timeDimensions && ramda_1.default.sortBy(([exprPath]) => exprPath, timeDimensions.map(d => [d.expressionPath(), d.rollupGranularity()])) || [];
|
|
356
355
|
}
|
|
357
356
|
static timeDimensionsAsIs(timeDimensions) {
|
|
358
|
-
return timeDimensions && ramda_1.default.sortBy(
|
|
357
|
+
return timeDimensions && ramda_1.default.sortBy(([exprPath]) => exprPath, timeDimensions.map(d => [d.expressionPath(), d.resolvedGranularity()])) || [];
|
|
359
358
|
}
|
|
360
359
|
static collectFilterDimensionsWithSingleValueEqual(filters, map) {
|
|
361
360
|
// eslint-disable-next-line no-restricted-syntax
|
|
@@ -374,6 +373,7 @@ class PreAggregations {
|
|
|
374
373
|
}
|
|
375
374
|
return map;
|
|
376
375
|
}
|
|
376
|
+
// FIXME: It seems to be not used at all
|
|
377
377
|
static transformedQueryToReferences(query) {
|
|
378
378
|
return {
|
|
379
379
|
measures: query.measures,
|
|
@@ -381,25 +381,18 @@ class PreAggregations {
|
|
|
381
381
|
timeDimensions: query.sortedTimeDimensions.map(([dimension, granularity]) => ({ dimension, granularity }))
|
|
382
382
|
};
|
|
383
383
|
}
|
|
384
|
-
canUsePreAggregationFn(query, refs) {
|
|
384
|
+
canUsePreAggregationFn(query, refs = null) {
|
|
385
385
|
return PreAggregations.canUsePreAggregationForTransformedQueryFn(PreAggregations.transformQueryToCanUseForm(query), refs);
|
|
386
386
|
}
|
|
387
387
|
/**
|
|
388
388
|
* Returns function to determine whether pre-aggregation can be used or not
|
|
389
389
|
* for specified query, or its value for `refs` if specified.
|
|
390
|
-
* @param {Object} transformedQuery transformed query
|
|
391
|
-
* @param {PreAggregationReferences?} refs pre-aggs reference
|
|
392
|
-
* @returns {function(preagg: Object): boolean}
|
|
393
390
|
*/
|
|
394
|
-
static canUsePreAggregationForTransformedQueryFn(transformedQuery, refs) {
|
|
391
|
+
static canUsePreAggregationForTransformedQueryFn(transformedQuery, refs = null) {
|
|
395
392
|
// TODO this needs to check not only members list, but their join paths as well:
|
|
396
393
|
// query can have same members as pre-agg, but different calculated join path
|
|
397
|
-
// `refs` will come from
|
|
394
|
+
// `refs` will come from pre-agg references, and would contain full join paths
|
|
398
395
|
// TODO remove this in favor of matching with join path
|
|
399
|
-
/**
|
|
400
|
-
* @param {PreAggregationReferences} references
|
|
401
|
-
* @returns {PreAggregationReferences}
|
|
402
|
-
*/
|
|
403
396
|
function trimmedReferences(references) {
|
|
404
397
|
const timeDimensionsTrimmed = references
|
|
405
398
|
.timeDimensions
|
|
@@ -413,27 +406,25 @@ class PreAggregations {
|
|
|
413
406
|
const dimensionsTrimmed = references
|
|
414
407
|
.dimensions
|
|
415
408
|
.map(d => CubeSymbols_1.CubeSymbols.joinHintFromPath(d).path);
|
|
409
|
+
const multipliedMeasuresTrimmed = references
|
|
410
|
+
.multipliedMeasures?.map(m => CubeSymbols_1.CubeSymbols.joinHintFromPath(m).path) || [];
|
|
416
411
|
return {
|
|
417
412
|
...references,
|
|
418
413
|
dimensions: dimensionsTrimmed,
|
|
419
414
|
measures: measuresTrimmed,
|
|
420
415
|
timeDimensions: timeDimensionsTrimmed,
|
|
416
|
+
multipliedMeasures: multipliedMeasuresTrimmed,
|
|
421
417
|
};
|
|
422
418
|
}
|
|
423
419
|
/**
|
|
424
420
|
* Returns an array of 2-elements arrays with the dimension and granularity
|
|
425
421
|
* sorted by the concatenated dimension + granularity key.
|
|
426
|
-
* @param {Array<{dimension: string, granularity: string}>} timeDimensions
|
|
427
|
-
* @returns {Array<Array<string>>}
|
|
428
422
|
*/
|
|
429
423
|
const sortTimeDimensions = (timeDimensions) => (timeDimensions &&
|
|
430
424
|
ramda_1.default.sortBy(d => d.join('.'), timeDimensions.map(d => [
|
|
431
425
|
d.dimension,
|
|
432
426
|
d.granularity || 'day', // TODO granularity shouldn't be null?
|
|
433
427
|
])) || []);
|
|
434
|
-
/**
|
|
435
|
-
* @type {Set<string>}
|
|
436
|
-
*/
|
|
437
428
|
const filterDimensionsSingleValueEqual = transformedQuery.filterDimensionsSingleValueEqual && (transformedQuery.filterDimensionsSingleValueEqual instanceof Set
|
|
438
429
|
? transformedQuery.filterDimensionsSingleValueEqual
|
|
439
430
|
: new Set(Object.keys(transformedQuery.filterDimensionsSingleValueEqual || {})));
|
|
@@ -442,8 +433,6 @@ class PreAggregations {
|
|
|
442
433
|
transformedQuery.allBackAliasMembers[r] || r));
|
|
443
434
|
/**
|
|
444
435
|
* Determine whether pre-aggregation can be used or not.
|
|
445
|
-
* @param {PreAggregationReferences} references
|
|
446
|
-
* @returns {boolean}
|
|
447
436
|
*/
|
|
448
437
|
const canUsePreAggregationNotAdditive = (references) => {
|
|
449
438
|
// TODO remove this in favor of matching with join path
|
|
@@ -499,12 +488,6 @@ class PreAggregations {
|
|
|
499
488
|
return expandGranularity(dimension, resolvedGranularity)
|
|
500
489
|
.map((newGranularity) => [dimension, newGranularity]);
|
|
501
490
|
};
|
|
502
|
-
/**
|
|
503
|
-
* Determine whether pre-aggregation can be used or not.
|
|
504
|
-
* TODO: revisit cumulative leaf measure matches.
|
|
505
|
-
* @param {PreAggregationReferences} references
|
|
506
|
-
* @returns {boolean}
|
|
507
|
-
*/
|
|
508
491
|
const canUsePreAggregationLeafMeasureAdditive = (references) => {
|
|
509
492
|
/**
|
|
510
493
|
* Array of 2-element arrays with dimension and granularity.
|
|
@@ -518,12 +501,22 @@ class PreAggregations {
|
|
|
518
501
|
: transformedQuery.ownedTimeDimensionsWithRollupGranularity.map(expandTimeDimension);
|
|
519
502
|
// TODO remove this in favor of matching with join path
|
|
520
503
|
const referencesTrimmed = trimmedReferences(references);
|
|
504
|
+
// Even if there are no multiplied measures in the query (because no multiplier dimensions are requested)
|
|
505
|
+
// but the same measures are multiplied in the pre-aggregation, we can't use pre-aggregation
|
|
506
|
+
// for such queries.
|
|
507
|
+
if (referencesTrimmed.multipliedMeasures) {
|
|
508
|
+
const backAliasMultipliedMeasures = backAlias(referencesTrimmed.multipliedMeasures);
|
|
509
|
+
if (transformedQuery.leafMeasures.some(m => referencesTrimmed.multipliedMeasures?.includes(m)) ||
|
|
510
|
+
transformedQuery.measures.some(m => backAliasMultipliedMeasures.includes(m))) {
|
|
511
|
+
return false;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
521
514
|
const dimensionsMatch = (dimensions, doBackAlias) => ramda_1.default.all(d => (doBackAlias ?
|
|
522
515
|
backAlias(referencesTrimmed.dimensions) :
|
|
523
516
|
(referencesTrimmed.dimensions)).indexOf(d) !== -1, dimensions);
|
|
524
|
-
const timeDimensionsMatch = (timeDimensionsList, doBackAlias) => ramda_1.default.allPass(timeDimensionsList.map(tds => ramda_1.default.anyPass(tds.map(td => {
|
|
517
|
+
const timeDimensionsMatch = (timeDimensionsList, doBackAlias) => ramda_1.default.allPass(timeDimensionsList.map(tds => ramda_1.default.anyPass(tds.map((td) => {
|
|
525
518
|
if (td[1] === '*') {
|
|
526
|
-
return ramda_1.default.any(tdtc => tdtc[0] === td[0]); // need to match the dimension at least
|
|
519
|
+
return ramda_1.default.any((tdtc) => tdtc[0] === td[0]); // need to match the dimension at least
|
|
527
520
|
}
|
|
528
521
|
else {
|
|
529
522
|
return ramda_1.default.contains(td);
|
|
@@ -532,44 +525,47 @@ class PreAggregations {
|
|
|
532
525
|
backAlias(sortTimeDimensions(referencesTrimmed.timeDimensions)) :
|
|
533
526
|
(sortTimeDimensions(referencesTrimmed.timeDimensions)));
|
|
534
527
|
if (transformedQuery.ungrouped) {
|
|
535
|
-
const allReferenceCubes = ramda_1.default.pipe(ramda_1.default.map(
|
|
528
|
+
const allReferenceCubes = ramda_1.default.pipe(ramda_1.default.map((name) => name?.split('.')[0]), ramda_1.default.uniq, ramda_1.default.sortBy(ramda_1.default.identity))([
|
|
529
|
+
...referencesTrimmed.measures,
|
|
530
|
+
...referencesTrimmed.dimensions,
|
|
531
|
+
...referencesTrimmed.timeDimensions.map(td => td.dimension),
|
|
532
|
+
]);
|
|
536
533
|
if (!ramda_1.default.equals(transformedQuery.sortedAllCubeNames, allReferenceCubes) ||
|
|
537
534
|
!(dimensionsMatch(transformedQuery.sortedUsedCubePrimaryKeys, true) || dimensionsMatch(transformedQuery.sortedUsedCubePrimaryKeys, false))) {
|
|
538
535
|
return false;
|
|
539
536
|
}
|
|
540
537
|
}
|
|
541
538
|
const backAliasMeasures = backAlias(referencesTrimmed.measures);
|
|
542
|
-
return ((windowGranularityMatches(references)) && (ramda_1.default.all(m => referencesTrimmed.measures.indexOf(m) !== -1, transformedQuery.leafMeasures) || ramda_1.default.all(m => backAliasMeasures.indexOf(m) !== -1, transformedQuery.measures)) && (dimensionsMatch(transformedQuery.sortedDimensions, true) && timeDimensionsMatch(queryTimeDimensionsList, true) ||
|
|
539
|
+
return ((windowGranularityMatches(references)) && (ramda_1.default.all((m) => referencesTrimmed.measures.indexOf(m) !== -1, transformedQuery.leafMeasures) || ramda_1.default.all(m => backAliasMeasures.indexOf(m) !== -1, transformedQuery.measures)) && (dimensionsMatch(transformedQuery.sortedDimensions, true) && timeDimensionsMatch(queryTimeDimensionsList, true) ||
|
|
543
540
|
dimensionsMatch(transformedQuery.ownedDimensions, false) && timeDimensionsMatch(ownedQueryTimeDimensionsList, false)));
|
|
544
541
|
};
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
* @returns {boolean}
|
|
548
|
-
*/
|
|
549
|
-
const canUseFn = (transformedQuery.leafMeasureAdditive && !transformedQuery.hasMultipliedMeasures && !transformedQuery.hasMultiStage || transformedQuery.ungrouped) ? (r) => canUsePreAggregationLeafMeasureAdditive(r) ||
|
|
550
|
-
canUsePreAggregationNotAdditive(r)
|
|
542
|
+
const canUseFn = (transformedQuery.leafMeasureAdditive && !transformedQuery.hasMultipliedMeasures && !transformedQuery.hasMultiStage || transformedQuery.ungrouped) ? ((r) => canUsePreAggregationLeafMeasureAdditive(r) ||
|
|
543
|
+
canUsePreAggregationNotAdditive(r))
|
|
551
544
|
: canUsePreAggregationNotAdditive;
|
|
552
545
|
if (refs) {
|
|
546
|
+
// @ts-ignore TS think it is boolean here
|
|
553
547
|
return canUseFn(refs);
|
|
554
548
|
}
|
|
555
549
|
else {
|
|
556
550
|
return canUseFn;
|
|
557
551
|
}
|
|
558
552
|
}
|
|
559
|
-
static squashDimensions(
|
|
560
|
-
return ramda_1.default.pipe(ramda_1.default.uniq, ramda_1.default.sortBy(ramda_1.default.identity))(flattenDimensionMembers
|
|
553
|
+
static squashDimensions(flattenDimensionMembers) {
|
|
554
|
+
return ramda_1.default.pipe(ramda_1.default.uniq, ramda_1.default.sortBy(ramda_1.default.identity))(flattenDimensionMembers
|
|
555
|
+
.filter((member) => typeof member.expressionPath === 'function')
|
|
556
|
+
.map(d => d.expressionPath()));
|
|
561
557
|
}
|
|
562
558
|
static flattenMembers(members) {
|
|
563
559
|
return ramda_1.default.flatten(members.map(m => m.getMembers()));
|
|
564
560
|
}
|
|
565
561
|
static flattenDimensionMembers(query) {
|
|
566
|
-
return this.flattenMembers(
|
|
567
|
-
|
|
568
|
-
|
|
562
|
+
return this.flattenMembers([
|
|
563
|
+
...query.dimensions,
|
|
564
|
+
...query.filters,
|
|
565
|
+
...query.segments,
|
|
566
|
+
]);
|
|
569
567
|
}
|
|
570
|
-
|
|
571
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
572
|
-
getCubeLattice(cube, preAggregationName, preAggregation) {
|
|
568
|
+
getCubeLattice(_cube, _preAggregationName, _preAggregation) {
|
|
573
569
|
throw new UserError_1.UserError('Auto rollups supported only in Enterprise version');
|
|
574
570
|
}
|
|
575
571
|
/**
|
|
@@ -577,22 +573,32 @@ class PreAggregations {
|
|
|
577
573
|
* from the list of potentially applicable pre-aggs). The order of the
|
|
578
574
|
* potentially applicable pre-aggs is the same as the order in which these
|
|
579
575
|
* pre-aggs appear in the schema file.
|
|
580
|
-
* @returns {Object}
|
|
581
576
|
*/
|
|
582
577
|
findPreAggregationForQuery() {
|
|
583
578
|
if (!this.preAggregationForQuery) {
|
|
584
|
-
this.
|
|
585
|
-
this
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
579
|
+
if (this.query.useNativeSqlPlanner && this.query.canUseNativeSqlPlannerPreAggregation) {
|
|
580
|
+
this.preAggregationForQuery = this.query.findPreAggregationForQueryRust();
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
this.preAggregationForQuery =
|
|
584
|
+
this
|
|
585
|
+
.rollupMatchResults()
|
|
586
|
+
// Refresh worker can access specific pre-aggregations even in case those hidden by others
|
|
587
|
+
.find(p => p.canUsePreAggregation && (!this.query.options.preAggregationId || p.preAggregationId === this.query.options.preAggregationId));
|
|
588
|
+
}
|
|
589
589
|
}
|
|
590
590
|
return this.preAggregationForQuery;
|
|
591
591
|
}
|
|
592
592
|
findAutoRollupPreAggregationsForCube(cube, preAggregations) {
|
|
593
|
-
if (
|
|
593
|
+
if (this.query.measures.some((m) => {
|
|
594
|
+
const path = m.path();
|
|
595
|
+
return path !== null && path[0] === cube;
|
|
596
|
+
}) ||
|
|
594
597
|
!this.query.measures.length && !this.query.timeDimensions.length &&
|
|
595
|
-
|
|
598
|
+
this.query.dimensions.every((d) => {
|
|
599
|
+
const path = d.path();
|
|
600
|
+
return path !== null && path[0] === cube;
|
|
601
|
+
})) {
|
|
596
602
|
return ramda_1.default.pipe(ramda_1.default.toPairs,
|
|
597
603
|
// eslint-disable-next-line no-unused-vars
|
|
598
604
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -600,7 +606,7 @@ class PreAggregations {
|
|
|
600
606
|
const cubeLattice = this.getCubeLattice(cube, preAggregationName, preAggregation);
|
|
601
607
|
const optimalPreAggregation = cubeLattice.findOptimalPreAggregationFromLattice(this.query);
|
|
602
608
|
return optimalPreAggregation && {
|
|
603
|
-
preAggregationName: preAggregationName + this.autoRollupNameSuffix(
|
|
609
|
+
preAggregationName: preAggregationName + this.autoRollupNameSuffix(optimalPreAggregation),
|
|
604
610
|
preAggregation: Object.assign(optimalPreAggregation, preAggregation),
|
|
605
611
|
cube,
|
|
606
612
|
canUsePreAggregation: true,
|
|
@@ -611,14 +617,13 @@ class PreAggregations {
|
|
|
611
617
|
return [];
|
|
612
618
|
}
|
|
613
619
|
/**
|
|
614
|
-
* Returns an array of potentially applicable for the query
|
|
620
|
+
* Returns an array of potentially applicable for the query pre-aggs in the
|
|
615
621
|
* same order they appear in the schema file.
|
|
616
|
-
* @returns {Array<Object>}
|
|
617
622
|
*/
|
|
618
623
|
rollupMatchResults() {
|
|
619
624
|
const { query } = this;
|
|
620
625
|
const canUsePreAggregation = this.canUsePreAggregationFn(query);
|
|
621
|
-
return ramda_1.default.pipe(ramda_1.default.map(cube => {
|
|
626
|
+
return ramda_1.default.pipe(ramda_1.default.map((cube) => {
|
|
622
627
|
const preAggregations = this.query.cubeEvaluator.preAggregationsForCube(cube);
|
|
623
628
|
let rollupPreAggregations = this.findRollupPreAggregationsForCube(cube, canUsePreAggregation, preAggregations);
|
|
624
629
|
rollupPreAggregations = rollupPreAggregations.concat(this.findAutoRollupPreAggregationsForCube(cube, preAggregations));
|
|
@@ -631,6 +636,21 @@ class PreAggregations {
|
|
|
631
636
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
632
637
|
ramda_1.default.filter(([k, a]) => a.type === 'rollup' || a.type === 'rollupJoin' || a.type === 'rollupLambda'), ramda_1.default.map(([preAggregationName, preAggregation]) => this.evaluatedPreAggregationObj(cube, preAggregationName, preAggregation, canUsePreAggregation)))(preAggregations);
|
|
633
638
|
}
|
|
639
|
+
getRollupPreAggregationByName(cube, preAggregationName) {
|
|
640
|
+
const canUsePreAggregation = () => true;
|
|
641
|
+
const preAggregation = ramda_1.default.pipe(ramda_1.default.toPairs, ramda_1.default.filter(([_, a]) => a.type === 'rollup' || a.type === 'rollupJoin' || a.type === 'rollupLambda'), ramda_1.default.find(([k, _]) => k === preAggregationName))(this.query.cubeEvaluator.preAggregationsForCube(cube));
|
|
642
|
+
if (preAggregation) {
|
|
643
|
+
const tableName = this.preAggregationTableName(cube, preAggregation[0], preAggregation[1]);
|
|
644
|
+
const preAggObj = preAggregation ? this.evaluatedPreAggregationObj(cube, preAggregation[0], preAggregation[1], canUsePreAggregation) : {};
|
|
645
|
+
return {
|
|
646
|
+
tableName,
|
|
647
|
+
...preAggObj
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
else {
|
|
651
|
+
return {};
|
|
652
|
+
}
|
|
653
|
+
}
|
|
634
654
|
// TODO check multiplication factor didn't change
|
|
635
655
|
buildRollupJoin(preAggObj, preAggObjsToJoin) {
|
|
636
656
|
return this.query.cacheValue(['buildRollupJoin', JSON.stringify(preAggObj), JSON.stringify(preAggObjsToJoin)], () => {
|
|
@@ -768,14 +788,21 @@ class PreAggregations {
|
|
|
768
788
|
return preAggregation.preAggregation.partitionGranularity;
|
|
769
789
|
}
|
|
770
790
|
static memberNameMismatchValidation(preAggA, preAggB, memberType) {
|
|
771
|
-
const preAggAMemberNames = PreAggregations.memberShortNames(preAggA.references[memberType]
|
|
772
|
-
const preAggBMemberNames = PreAggregations.memberShortNames(preAggB.references[memberType]
|
|
791
|
+
const preAggAMemberNames = PreAggregations.memberShortNames(preAggA.references[memberType]);
|
|
792
|
+
const preAggBMemberNames = PreAggregations.memberShortNames(preAggB.references[memberType]);
|
|
773
793
|
if (!ramda_1.default.equals(preAggAMemberNames, preAggBMemberNames)) {
|
|
774
794
|
throw new UserError_1.UserError(`Names for ${memberType} doesn't match between '${preAggA.cube}.${preAggA.preAggregationName}' and '${preAggB.cube}.${preAggB.preAggregationName}': ${JSON.stringify(preAggAMemberNames)} does not equal to ${JSON.stringify(preAggBMemberNames)}`);
|
|
775
795
|
}
|
|
776
796
|
}
|
|
777
|
-
static memberShortNames(memberArray
|
|
778
|
-
return memberArray.map(member =>
|
|
797
|
+
static memberShortNames(memberArray) {
|
|
798
|
+
return memberArray.map(member => {
|
|
799
|
+
if (typeof member !== 'string') {
|
|
800
|
+
return `${member.dimension.split('.')[1]}.${member.granularity}`;
|
|
801
|
+
}
|
|
802
|
+
else {
|
|
803
|
+
return member.split('.')[1];
|
|
804
|
+
}
|
|
805
|
+
});
|
|
779
806
|
}
|
|
780
807
|
rollupMatchResultDescriptions() {
|
|
781
808
|
return this.rollupMatchResults().map(p => ({
|
|
@@ -789,7 +816,7 @@ class PreAggregations {
|
|
|
789
816
|
return PreAggregations.transformQueryToCanUseForm(this.query);
|
|
790
817
|
}
|
|
791
818
|
static hasCumulativeMeasures(query) {
|
|
792
|
-
const measures =
|
|
819
|
+
const measures = [...query.measures, ...query.measureFilters];
|
|
793
820
|
const collectLeafMeasures = query.collectLeafMeasures.bind(query);
|
|
794
821
|
return ramda_1.default.pipe(ramda_1.default.map(m => query.collectFrom([m], collectLeafMeasures, 'collectLeafMeasures')), ramda_1.default.unnest, ramda_1.default.uniq, ramda_1.default.map(p => query.newMeasure(p)), ramda_1.default.any(m => m.isCumulative()))(measures);
|
|
795
822
|
}
|
|
@@ -816,11 +843,11 @@ class PreAggregations {
|
|
|
816
843
|
preAggregationQuery: true,
|
|
817
844
|
});
|
|
818
845
|
}
|
|
819
|
-
rollupPreAggregationQuery(cube, aggregation) {
|
|
846
|
+
rollupPreAggregationQuery(cube, aggregation, context = {}) {
|
|
820
847
|
// `this.evaluateAllReferences` will retain not only members, but their join path as well, and pass join hints
|
|
821
848
|
// to subquery. Otherwise, members in subquery would regenerate new join tree from clean state,
|
|
822
849
|
// and it can be different from expected by join path in pre-aggregation declaration
|
|
823
|
-
const references = this.evaluateAllReferences(cube, aggregation);
|
|
850
|
+
const references = this.evaluateAllReferences(cube, aggregation, null, context);
|
|
824
851
|
const cubeQuery = this.query.newSubQueryForCube(cube, {});
|
|
825
852
|
return this.query.newSubQueryForCube(cube, {
|
|
826
853
|
rowLimit: null,
|
|
@@ -861,7 +888,7 @@ class PreAggregations {
|
|
|
861
888
|
return toMerge ? { ...d, dateRange: toMerge.dateRange, boundaryDateRange: toMerge.boundaryDateRange } : d;
|
|
862
889
|
});
|
|
863
890
|
}
|
|
864
|
-
autoRollupNameSuffix(
|
|
891
|
+
autoRollupNameSuffix(aggregation) {
|
|
865
892
|
// eslint-disable-next-line prefer-template
|
|
866
893
|
return '_' + aggregation.dimensions.concat(aggregation.timeDimensions.map(d => `${d.dimension}${d.granularity.substring(0, 1)}`)).map(s => {
|
|
867
894
|
const path = s.split('.');
|
|
@@ -870,19 +897,17 @@ class PreAggregations {
|
|
|
870
897
|
.replace(/[.]/g, '')
|
|
871
898
|
.toLowerCase();
|
|
872
899
|
}
|
|
873
|
-
|
|
874
|
-
*
|
|
875
|
-
* @param {string} cube
|
|
876
|
-
* @param aggregation
|
|
877
|
-
* @param {string} [preAggregationName]
|
|
878
|
-
* @returns {PreAggregationReferences}
|
|
879
|
-
*/
|
|
880
|
-
evaluateAllReferences(cube, aggregation, preAggregationName) {
|
|
900
|
+
evaluateAllReferences(cube, aggregation, preAggregationName = null, context = {}) {
|
|
881
901
|
// TODO build a join tree for all references, so they would always include full join path
|
|
882
902
|
// Even for preaggregation references without join path
|
|
883
903
|
// It is necessary to be able to match query and preaggregation based on full join tree
|
|
884
904
|
const evaluateReferences = () => {
|
|
885
905
|
const references = this.query.cubeEvaluator.evaluatePreAggregationReferences(cube, aggregation);
|
|
906
|
+
if (!context.inPreAggEvaluation) {
|
|
907
|
+
const preAggQuery = this.query.preAggregationQueryForSqlEvaluation(cube, aggregation, { inPreAggEvaluation: true });
|
|
908
|
+
const aggregateMeasures = preAggQuery?.fullKeyQueryAggregateMeasures({ hasMultipliedForPreAggregation: true });
|
|
909
|
+
references.multipliedMeasures = aggregateMeasures?.multipliedMeasures?.map(m => m.measure);
|
|
910
|
+
}
|
|
886
911
|
if (aggregation.type === 'rollupLambda') {
|
|
887
912
|
if (references.rollups.length > 0) {
|
|
888
913
|
const [firstLambdaCube] = this.query.cubeEvaluator.parsePath('preAggregations', references.rollups[0]);
|
|
@@ -909,7 +934,7 @@ class PreAggregations {
|
|
|
909
934
|
// eslint-disable-next-line prefer-const
|
|
910
935
|
let { preAggregationName, preAggregation } = preAggregationDescription;
|
|
911
936
|
// @todo Dont use sqlAlias directly, we needed to move it in preAggregationTableName
|
|
912
|
-
if (preAggregation
|
|
937
|
+
if (preAggregation?.sqlAlias) {
|
|
913
938
|
preAggregationName = preAggregation.sqlAlias;
|
|
914
939
|
}
|
|
915
940
|
return this.query.preAggregationTableName(preAggregationDescription.cube, preAggregationName);
|
|
@@ -984,10 +1009,9 @@ class PreAggregations {
|
|
|
984
1009
|
toJoin = [sqlAndAlias(preAggregationForQuery)];
|
|
985
1010
|
}
|
|
986
1011
|
const from = this.query.joinSql(toJoin);
|
|
987
|
-
const replacedFilters = filters || this.query.segments
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
}))).filter(f => !!f);
|
|
1012
|
+
const replacedFilters = filters || [...this.query.segments, ...this.query.filters, ...(this.query.timeDimensions.map(dimension => dimension.dateRange && ({
|
|
1013
|
+
filterToWhere: () => this.query.timeRangeFilter(this.query.dimensionSql(dimension), dimension.localDateTimeFromParam(), dimension.localDateTimeToParam()),
|
|
1014
|
+
})))].filter(f => !!f);
|
|
991
1015
|
const renderedReference = {
|
|
992
1016
|
...(this.measuresRenderedReference(preAggregationForQuery)),
|
|
993
1017
|
...(this.dimensionsRenderedReference(preAggregationForQuery)),
|
|
@@ -1007,43 +1031,76 @@ class PreAggregations {
|
|
|
1007
1031
|
});
|
|
1008
1032
|
}
|
|
1009
1033
|
measuresRenderedReference(preAggregationForQuery) {
|
|
1010
|
-
|
|
1034
|
+
const measures = this.rollupMeasures(preAggregationForQuery);
|
|
1035
|
+
return Object.fromEntries(measures
|
|
1036
|
+
.flatMap(path => {
|
|
1011
1037
|
const measure = this.query.newMeasure(path);
|
|
1038
|
+
const measurePath = measure.path();
|
|
1039
|
+
const column = this.query.ungrouped ? measure.aliasName() : (this.query.aggregateOnGroupedColumn(measure.measureDefinition(), measure.aliasName(), !this.query.safeEvaluateSymbolContext().overTimeSeriesAggregate, path) || `sum(${measure.aliasName()})`);
|
|
1040
|
+
if (measurePath === null) {
|
|
1041
|
+
return [[path, column]];
|
|
1042
|
+
}
|
|
1043
|
+
const memberPath = this.query.cubeEvaluator.pathFromArray(measurePath);
|
|
1044
|
+
// Return both full join path and measure path
|
|
1012
1045
|
return [
|
|
1013
|
-
path,
|
|
1014
|
-
|
|
1046
|
+
[path, column],
|
|
1047
|
+
[memberPath, column],
|
|
1015
1048
|
];
|
|
1016
|
-
})
|
|
1049
|
+
}));
|
|
1017
1050
|
}
|
|
1018
1051
|
measureAliasesRenderedReference(preAggregationForQuery) {
|
|
1019
|
-
|
|
1052
|
+
const measures = this.rollupMeasures(preAggregationForQuery);
|
|
1053
|
+
return Object.fromEntries(measures
|
|
1054
|
+
.flatMap(path => {
|
|
1020
1055
|
const measure = this.query.newMeasure(path);
|
|
1056
|
+
const measurePath = measure.path();
|
|
1057
|
+
const alias = measure.aliasName();
|
|
1058
|
+
if (measurePath === null) {
|
|
1059
|
+
return [[path, alias]];
|
|
1060
|
+
}
|
|
1061
|
+
const memberPath = this.query.cubeEvaluator.pathFromArray(measurePath);
|
|
1062
|
+
// Return both full join path and measure path
|
|
1021
1063
|
return [
|
|
1022
|
-
path,
|
|
1023
|
-
|
|
1064
|
+
[path, alias],
|
|
1065
|
+
[memberPath, alias],
|
|
1024
1066
|
];
|
|
1025
|
-
})
|
|
1067
|
+
}));
|
|
1026
1068
|
}
|
|
1027
1069
|
dimensionsRenderedReference(preAggregationForQuery) {
|
|
1028
|
-
|
|
1070
|
+
const dimensions = this.rollupDimensions(preAggregationForQuery);
|
|
1071
|
+
return Object.fromEntries(dimensions
|
|
1072
|
+
.flatMap(path => {
|
|
1029
1073
|
const dimension = this.query.newDimension(path);
|
|
1074
|
+
const dimensionPath = dimension.path();
|
|
1075
|
+
const column = this.query.escapeColumnName(dimension.unescapedAliasName());
|
|
1076
|
+
if (dimensionPath === null) {
|
|
1077
|
+
return [[path, column]];
|
|
1078
|
+
}
|
|
1079
|
+
const memberPath = this.query.cubeEvaluator.pathFromArray(dimensionPath);
|
|
1080
|
+
// Return both full join path and dimension path
|
|
1030
1081
|
return [
|
|
1031
|
-
path,
|
|
1032
|
-
|
|
1082
|
+
[path, column],
|
|
1083
|
+
[memberPath, column],
|
|
1033
1084
|
];
|
|
1034
|
-
})
|
|
1085
|
+
}));
|
|
1035
1086
|
}
|
|
1036
1087
|
timeDimensionsRenderedReference(rollupGranularity, preAggregationForQuery) {
|
|
1037
|
-
|
|
1088
|
+
const timeDimensions = this.rollupTimeDimensions(preAggregationForQuery);
|
|
1089
|
+
return Object.fromEntries(timeDimensions
|
|
1090
|
+
.flatMap(td => {
|
|
1038
1091
|
const timeDimension = this.query.newTimeDimension(td);
|
|
1092
|
+
const column = this.query.escapeColumnName(timeDimension.unescapedAliasName(rollupGranularity));
|
|
1093
|
+
const memberPath = this.query.cubeEvaluator.pathFromArray(timeDimension.path());
|
|
1094
|
+
// Return both full join path and dimension path
|
|
1039
1095
|
return [
|
|
1040
|
-
td.dimension,
|
|
1041
|
-
|
|
1096
|
+
[td.dimension, column],
|
|
1097
|
+
[memberPath, column],
|
|
1042
1098
|
];
|
|
1043
|
-
})
|
|
1099
|
+
}));
|
|
1044
1100
|
}
|
|
1045
1101
|
rollupMembers(preAggregationForQuery, type) {
|
|
1046
1102
|
return preAggregationForQuery.preAggregation.type === 'autoRollup' ?
|
|
1103
|
+
// TODO proper types
|
|
1047
1104
|
preAggregationForQuery.preAggregation[type] :
|
|
1048
1105
|
this.evaluateAllReferences(preAggregationForQuery.cube, preAggregationForQuery.preAggregation, preAggregationForQuery.preAggregationName)[type];
|
|
1049
1106
|
}
|