Skip to content

Commit aa65129

Browse files
committed
fix: Time dimension can't be selected twice within same query with and without granularity
1 parent 472a0c3 commit aa65129

File tree

7 files changed

+570
-43
lines changed

7 files changed

+570
-43
lines changed

packages/cubejs-api-gateway/index.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ const prepareAnnotation = (metaConfig, query) => {
2222

2323
const annotation = (memberType) => (member) => {
2424
const path = member.split('.');
25-
const config = configMap[path[0]][memberType].find(m => m.name === member);
25+
const memberWithoutGranularity = [path[0], path[1]].join('.');
26+
const config = configMap[path[0]][memberType].find(m => m.name === memberWithoutGranularity);
2627
if (!config) {
2728
return undefined;
2829
}
@@ -39,7 +40,10 @@ const prepareAnnotation = (metaConfig, query) => {
3940
measures: R.fromPairs((query.measures || []).map(annotation('measures')).filter(a => !!a)),
4041
dimensions: R.fromPairs((query.dimensions || []).map(annotation('dimensions')).filter(a => !!a)),
4142
segments: R.fromPairs((query.segments || []).map(annotation('segments')).filter(a => !!a)),
42-
timeDimensions: R.fromPairs((query.timeDimensions || []).map(td => annotation('dimensions')(td.dimension)).filter(a => !!a)), // TODO
43+
timeDimensions: R.fromPairs((query.timeDimensions || [])
44+
.filter(td => !!td.granularity)
45+
.map(td => annotation('dimensions')(`${td.dimension}.${td.granularity}`))
46+
.filter(a => !!a)),
4347
};
4448
};
4549

@@ -59,11 +63,28 @@ const transformData = (aliasToMemberNameMap, annotation, data) => (data.map(r =>
5963
if (!annotationForMember) {
6064
throw new UserError(`You requested hidden member: '${p[0]}'. Please make it visible using \`shown: true\``);
6165
}
62-
return [
66+
const transformResult = [
6367
memberName,
6468
transformValue(p[1], annotationForMember.type)
6569
];
70+
71+
const path = memberName.split('.');
72+
73+
// TODO: deprecated: backward compatibility for referencing time dimensions without granularity
74+
const memberNameWithoutGranularity = [path[0], path[1]].join('.');
75+
if (path.length === 3 && !annotation[memberNameWithoutGranularity]) {
76+
return [
77+
transformResult,
78+
[
79+
memberNameWithoutGranularity,
80+
transformResult[1]
81+
]
82+
];
83+
}
84+
85+
return [transformResult];
6686
}),
87+
R.unnest,
6788
R.fromPairs
6889
)(r)));
6990

packages/cubejs-client-core/dist/cubejs-client-core.esm.js

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -185,20 +185,34 @@ function () {
185185
var timeDimensions = (query.timeDimensions || []).filter(function (td) {
186186
return !!td.granularity;
187187
});
188+
var dimensions = query.dimensions || [];
188189
pivotConfig = pivotConfig || (timeDimensions.length ? {
189190
x: timeDimensions.map(function (td) {
190-
return td.dimension;
191+
return ResultSet.timeDimensionMember(td);
191192
}),
192-
y: query.dimensions || []
193+
y: dimensions
193194
} : {
194-
x: query.dimensions || [],
195+
x: dimensions,
195196
y: []
196197
});
197-
pivotConfig.x = pivotConfig.x || [];
198-
pivotConfig.y = pivotConfig.y || [];
198+
199+
var substituteTimeDimensionMembers = function substituteTimeDimensionMembers(axis) {
200+
return axis.map(function (subDim) {
201+
return timeDimensions.find(function (td) {
202+
return td.dimension === subDim;
203+
}) && !dimensions.find(function (d) {
204+
return d === subDim;
205+
}) ? ResultSet.timeDimensionMember(query.timeDimensions.find(function (td) {
206+
return td.dimension === subDim;
207+
})) : subDim;
208+
});
209+
};
210+
211+
pivotConfig.x = substituteTimeDimensionMembers(pivotConfig.x || []);
212+
pivotConfig.y = substituteTimeDimensionMembers(pivotConfig.y || []);
199213
var allIncludedDimensions = pivotConfig.x.concat(pivotConfig.y);
200214
var allDimensions = timeDimensions.map(function (td) {
201-
return td.dimension;
215+
return ResultSet.timeDimensionMember(td);
202216
}).concat(query.dimensions);
203217
pivotConfig.x = pivotConfig.x.concat(allDimensions.filter(function (d) {
204218
return allIncludedDimensions.indexOf(d) === -1;
@@ -236,7 +250,7 @@ function () {
236250

237251
if (!dateRange) {
238252
var dates = pipe(map(function (row) {
239-
return row[timeDimension.dimension] && moment(row[timeDimension.dimension]);
253+
return row[ResultSet.timeDimensionMember(timeDimension)] && moment(row[ResultSet.timeDimensionMember(timeDimension)]);
240254
}), filter(function (r) {
241255
return !!r;
242256
}))(this.loadResponse.data);
@@ -280,7 +294,7 @@ function () {
280294
if (pivotConfig.fillMissingDates && pivotConfig.x.length === 1 && equals(pivotConfig.x, (this.loadResponse.query.timeDimensions || []).filter(function (td) {
281295
return !!td.granularity;
282296
}).map(function (td) {
283-
return td.dimension;
297+
return ResultSet.timeDimensionMember(td);
284298
}))) {
285299
var series = this.timeSeries(this.loadResponse.query.timeDimensions[0]);
286300

@@ -450,7 +464,7 @@ function () {
450464
}, {
451465
key: "tablePivot",
452466
value: function tablePivot(pivotConfig) {
453-
var normalizedPivotConfig = this.normalizePivotConfig(pivotConfig);
467+
var normalizedPivotConfig = this.normalizePivotConfig(pivotConfig || {});
454468

455469
var valueToObject = function valueToObject(valuesArray, measureValue) {
456470
return function (field, index) {
@@ -584,6 +598,11 @@ function () {
584598
return this.loadResponse.data;
585599
}
586600
}], [{
601+
key: "timeDimensionMember",
602+
value: function timeDimensionMember(td) {
603+
return "".concat(td.dimension, ".").concat(td.granularity);
604+
}
605+
}, {
587606
key: "measureFromAxis",
588607
value: function measureFromAxis(axisValues) {
589608
return axisValues[axisValues.length - 1];

packages/cubejs-client-core/dist/cubejs-client-core.js

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -191,20 +191,34 @@ function () {
191191
var timeDimensions = (query.timeDimensions || []).filter(function (td) {
192192
return !!td.granularity;
193193
});
194+
var dimensions = query.dimensions || [];
194195
pivotConfig = pivotConfig || (timeDimensions.length ? {
195196
x: timeDimensions.map(function (td) {
196-
return td.dimension;
197+
return ResultSet.timeDimensionMember(td);
197198
}),
198-
y: query.dimensions || []
199+
y: dimensions
199200
} : {
200-
x: query.dimensions || [],
201+
x: dimensions,
201202
y: []
202203
});
203-
pivotConfig.x = pivotConfig.x || [];
204-
pivotConfig.y = pivotConfig.y || [];
204+
205+
var substituteTimeDimensionMembers = function substituteTimeDimensionMembers(axis) {
206+
return axis.map(function (subDim) {
207+
return timeDimensions.find(function (td) {
208+
return td.dimension === subDim;
209+
}) && !dimensions.find(function (d) {
210+
return d === subDim;
211+
}) ? ResultSet.timeDimensionMember(query.timeDimensions.find(function (td) {
212+
return td.dimension === subDim;
213+
})) : subDim;
214+
});
215+
};
216+
217+
pivotConfig.x = substituteTimeDimensionMembers(pivotConfig.x || []);
218+
pivotConfig.y = substituteTimeDimensionMembers(pivotConfig.y || []);
205219
var allIncludedDimensions = pivotConfig.x.concat(pivotConfig.y);
206220
var allDimensions = timeDimensions.map(function (td) {
207-
return td.dimension;
221+
return ResultSet.timeDimensionMember(td);
208222
}).concat(query.dimensions);
209223
pivotConfig.x = pivotConfig.x.concat(allDimensions.filter(function (d) {
210224
return allIncludedDimensions.indexOf(d) === -1;
@@ -242,7 +256,7 @@ function () {
242256

243257
if (!dateRange) {
244258
var dates = ramda.pipe(ramda.map(function (row) {
245-
return row[timeDimension.dimension] && moment(row[timeDimension.dimension]);
259+
return row[ResultSet.timeDimensionMember(timeDimension)] && moment(row[ResultSet.timeDimensionMember(timeDimension)]);
246260
}), ramda.filter(function (r) {
247261
return !!r;
248262
}))(this.loadResponse.data);
@@ -286,7 +300,7 @@ function () {
286300
if (pivotConfig.fillMissingDates && pivotConfig.x.length === 1 && ramda.equals(pivotConfig.x, (this.loadResponse.query.timeDimensions || []).filter(function (td) {
287301
return !!td.granularity;
288302
}).map(function (td) {
289-
return td.dimension;
303+
return ResultSet.timeDimensionMember(td);
290304
}))) {
291305
var series = this.timeSeries(this.loadResponse.query.timeDimensions[0]);
292306

@@ -456,7 +470,7 @@ function () {
456470
}, {
457471
key: "tablePivot",
458472
value: function tablePivot(pivotConfig) {
459-
var normalizedPivotConfig = this.normalizePivotConfig(pivotConfig);
473+
var normalizedPivotConfig = this.normalizePivotConfig(pivotConfig || {});
460474

461475
var valueToObject = function valueToObject(valuesArray, measureValue) {
462476
return function (field, index) {
@@ -590,6 +604,11 @@ function () {
590604
return this.loadResponse.data;
591605
}
592606
}], [{
607+
key: "timeDimensionMember",
608+
value: function timeDimensionMember(td) {
609+
return "".concat(td.dimension, ".").concat(td.granularity);
610+
}
611+
}, {
593612
key: "measureFromAxis",
594613
value: function measureFromAxis(axisValues) {
595614
return axisValues[axisValues.length - 1];

packages/cubejs-client-core/dist/cubejs-client-core.umd.js

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,7 @@
675675
// Set @@toStringTag to native iterators
676676
_setToStringTag(IteratorPrototype, TAG, true);
677677
// fix for some old engines
678-
if (typeof IteratorPrototype[ITERATOR] != 'function') _hide(IteratorPrototype, ITERATOR, returnThis);
678+
if (!_library && typeof IteratorPrototype[ITERATOR] != 'function') _hide(IteratorPrototype, ITERATOR, returnThis);
679679
}
680680
}
681681
// fix Array#{values, @@iterator}.name in V8 / FF
@@ -684,7 +684,7 @@
684684
$default = function values() { return $native.call(this); };
685685
}
686686
// Define iterator
687-
if (BUGGY || VALUES_BUG || !proto[ITERATOR]) {
687+
if ((!_library || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {
688688
_hide(proto, ITERATOR, $default);
689689
}
690690
// Plug for library
@@ -12746,20 +12746,34 @@
1274612746
var timeDimensions = (query.timeDimensions || []).filter(function (td) {
1274712747
return !!td.granularity;
1274812748
});
12749+
var dimensions = query.dimensions || [];
1274912750
pivotConfig = pivotConfig || (timeDimensions.length ? {
1275012751
x: timeDimensions.map(function (td) {
12751-
return td.dimension;
12752+
return ResultSet.timeDimensionMember(td);
1275212753
}),
12753-
y: query.dimensions || []
12754+
y: dimensions
1275412755
} : {
12755-
x: query.dimensions || [],
12756+
x: dimensions,
1275612757
y: []
1275712758
});
12758-
pivotConfig.x = pivotConfig.x || [];
12759-
pivotConfig.y = pivotConfig.y || [];
12759+
12760+
var substituteTimeDimensionMembers = function substituteTimeDimensionMembers(axis) {
12761+
return axis.map(function (subDim) {
12762+
return timeDimensions.find(function (td) {
12763+
return td.dimension === subDim;
12764+
}) && !dimensions.find(function (d) {
12765+
return d === subDim;
12766+
}) ? ResultSet.timeDimensionMember(query.timeDimensions.find(function (td) {
12767+
return td.dimension === subDim;
12768+
})) : subDim;
12769+
});
12770+
};
12771+
12772+
pivotConfig.x = substituteTimeDimensionMembers(pivotConfig.x || []);
12773+
pivotConfig.y = substituteTimeDimensionMembers(pivotConfig.y || []);
1276012774
var allIncludedDimensions = pivotConfig.x.concat(pivotConfig.y);
1276112775
var allDimensions = timeDimensions.map(function (td) {
12762-
return td.dimension;
12776+
return ResultSet.timeDimensionMember(td);
1276312777
}).concat(query.dimensions);
1276412778
pivotConfig.x = pivotConfig.x.concat(allDimensions.filter(function (d) {
1276512779
return allIncludedDimensions.indexOf(d) === -1;
@@ -12797,7 +12811,7 @@
1279712811

1279812812
if (!dateRange) {
1279912813
var dates = pipe(map(function (row) {
12800-
return row[timeDimension.dimension] && moment$1(row[timeDimension.dimension]);
12814+
return row[ResultSet.timeDimensionMember(timeDimension)] && moment$1(row[ResultSet.timeDimensionMember(timeDimension)]);
1280112815
}), filter(function (r) {
1280212816
return !!r;
1280312817
}))(this.loadResponse.data);
@@ -12841,7 +12855,7 @@
1284112855
if (pivotConfig.fillMissingDates && pivotConfig.x.length === 1 && equals(pivotConfig.x, (this.loadResponse.query.timeDimensions || []).filter(function (td) {
1284212856
return !!td.granularity;
1284312857
}).map(function (td) {
12844-
return td.dimension;
12858+
return ResultSet.timeDimensionMember(td);
1284512859
}))) {
1284612860
var series = this.timeSeries(this.loadResponse.query.timeDimensions[0]);
1284712861

@@ -13011,7 +13025,7 @@
1301113025
}, {
1301213026
key: "tablePivot",
1301313027
value: function tablePivot(pivotConfig) {
13014-
var normalizedPivotConfig = this.normalizePivotConfig(pivotConfig);
13028+
var normalizedPivotConfig = this.normalizePivotConfig(pivotConfig || {});
1301513029

1301613030
var valueToObject = function valueToObject(valuesArray, measureValue) {
1301713031
return function (field, index) {
@@ -13145,6 +13159,11 @@
1314513159
return this.loadResponse.data;
1314613160
}
1314713161
}], [{
13162+
key: "timeDimensionMember",
13163+
value: function timeDimensionMember(td) {
13164+
return "".concat(td.dimension, ".").concat(td.granularity);
13165+
}
13166+
}, {
1314813167
key: "measureFromAxis",
1314913168
value: function measureFromAxis(axisValues) {
1315013169
return axisValues[axisValues.length - 1];

packages/cubejs-client-core/src/ResultSet.js

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,20 +99,36 @@ class ResultSet {
9999
return axisValues.map(formatValue).join(delimiter || ', ');
100100
}
101101

102+
static timeDimensionMember(td) {
103+
return `${td.dimension}.${td.granularity}`;
104+
}
105+
102106
normalizePivotConfig(pivotConfig) {
103107
const { query } = this.loadResponse;
104108
const timeDimensions = (query.timeDimensions || []).filter(td => !!td.granularity);
109+
const dimensions = query.dimensions || [];
105110
pivotConfig = pivotConfig || (timeDimensions.length ? {
106-
x: timeDimensions.map(td => td.dimension),
107-
y: query.dimensions || []
111+
x: timeDimensions.map(td => ResultSet.timeDimensionMember(td)),
112+
y: dimensions
108113
} : {
109-
x: query.dimensions || [],
114+
x: dimensions,
110115
y: []
111116
});
112-
pivotConfig.x = pivotConfig.x || [];
113-
pivotConfig.y = pivotConfig.y || [];
117+
118+
const substituteTimeDimensionMembers = axis => axis.map(
119+
subDim => (
120+
timeDimensions.find(td => td.dimension === subDim) &&
121+
!dimensions.find(d => d === subDim) ?
122+
ResultSet.timeDimensionMember(query.timeDimensions.find(td => td.dimension === subDim)) :
123+
subDim
124+
)
125+
);
126+
127+
pivotConfig.x = substituteTimeDimensionMembers(pivotConfig.x || []);
128+
pivotConfig.y = substituteTimeDimensionMembers(pivotConfig.y || []);
129+
114130
const allIncludedDimensions = pivotConfig.x.concat(pivotConfig.y);
115-
const allDimensions = timeDimensions.map(td => td.dimension).concat(query.dimensions);
131+
const allDimensions = timeDimensions.map(td => ResultSet.timeDimensionMember(td)).concat(query.dimensions);
116132
pivotConfig.x = pivotConfig.x.concat(allDimensions.filter(d => allIncludedDimensions.indexOf(d) === -1));
117133
if (!pivotConfig.x.concat(pivotConfig.y).find(d => d === 'measures')) {
118134
pivotConfig.y = pivotConfig.y.concat(['measures']);
@@ -138,7 +154,10 @@ class ResultSet {
138154
let { dateRange } = timeDimension;
139155
if (!dateRange) {
140156
const dates = pipe(
141-
map(row => row[timeDimension.dimension] && moment(row[timeDimension.dimension])),
157+
map(
158+
row => row[ResultSet.timeDimensionMember(timeDimension)] &&
159+
moment(row[ResultSet.timeDimensionMember(timeDimension)])
160+
),
142161
filter(r => !!r)
143162
)(this.loadResponse.data);
144163

@@ -172,7 +191,9 @@ class ResultSet {
172191
pivotConfig.x.length === 1 &&
173192
equals(
174193
pivotConfig.x,
175-
(this.loadResponse.query.timeDimensions || []).filter(td => !!td.granularity).map(td => td.dimension)
194+
(this.loadResponse.query.timeDimensions || [])
195+
.filter(td => !!td.granularity)
196+
.map(td => ResultSet.timeDimensionMember(td))
176197
)
177198
) {
178199
const series = this.timeSeries(this.loadResponse.query.timeDimensions[0]);
@@ -299,7 +320,7 @@ class ResultSet {
299320
* @returns {Array} of pivoted rows
300321
*/
301322
tablePivot(pivotConfig) {
302-
const normalizedPivotConfig = this.normalizePivotConfig(pivotConfig);
323+
const normalizedPivotConfig = this.normalizePivotConfig(pivotConfig || {});
303324
const valueToObject =
304325
(valuesArray, measureValue) => (
305326
(field, index) => ({

0 commit comments

Comments
 (0)