Skip to content

Commit 7bdc47f

Browse files
committed
feat(tesseract): Switch dimensions and case measures
1 parent b778b76 commit 7bdc47f

File tree

15 files changed

+849
-88
lines changed

15 files changed

+849
-88
lines changed

packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3232,6 +3232,9 @@ export class BaseQuery {
32323232
}
32333233
if (symbol.case) {
32343234
return this.renderDimensionCase(symbol, cubeName);
3235+
} else if (symbol.type === 'switch') {
3236+
// Dimension of type switch is not supported in BaseQuery, return an empty string to make dependency resolution work.
3237+
return '';
32353238
} else if (symbol.type === 'geo') {
32363239
return this.concatStringsSql([
32373240
this.autoPrefixAndEvaluateSql(cubeName, symbol.latitude.sql, isMemberExpr),
@@ -4210,7 +4213,18 @@ export class BaseQuery {
42104213
time_series_get_range: 'SELECT {{ max_expr }} as {{ quoted_max_name }},\n' +
42114214
'{{ min_expr }} as {{ quoted_min_name }}\n' +
42124215
'FROM {{ from_prepared }}\n' +
4213-
'{% if filter %}WHERE {{ filter }}{% endif %}'
4216+
'{% if filter %}WHERE {{ filter }}{% endif %}',
4217+
calc_groups_join: 'SELECT \"{{ original_cube }}\".*, \"{{ groups | map(attribute=\'name\') | join(\'\", \"\') }}\"\n' +
4218+
'FROM {{ original_cube_sql }} {{ original_cube }}\n' +
4219+
'{% for group in groups %}' +
4220+
'CROSS JOIN\n' +
4221+
'(\n' +
4222+
'{% for value in group.values %}' +
4223+
'SELECT \'{{ value }}\' as \"{{ group.name }}\"' +
4224+
'{% if not loop.last %} UNION ALL\n{% endif %}' +
4225+
'{% endfor %}' +
4226+
') \"{{ group.name }}_values\"\n' +
4227+
'{% endfor %}'
42144228
},
42154229
expressions: {
42164230
column_reference: '{% if table_name %}{{ table_name }}.{% endif %}{{ name }}',

packages/cubejs-schema-compiler/src/compiler/CubeValidator.ts

Lines changed: 61 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ const BaseDimensionWithoutSubQuery = {
132132
enableSuggestions: Joi.boolean().strict(),
133133
format: formatSchema,
134134
meta: Joi.any(),
135+
values: Joi.when('type', {
136+
is: 'switch',
137+
then: Joi.array().items(Joi.string()),
138+
otherwise: Joi.forbidden()
139+
}),
135140
granularities: Joi.when('type', {
136141
is: 'time',
137142
then: Joi.object().pattern(identifierRegex,
@@ -647,53 +652,62 @@ const CalendarTimeShiftItem = Joi.alternatives().try(
647652
})
648653
);
649654

650-
const DimensionsSchema = Joi.object().pattern(identifierRegex, Joi.alternatives().try(
651-
inherit(BaseDimensionWithoutSubQuery, {
652-
case: Joi.object().keys({
653-
when: Joi.array().items(Joi.object().keys({
654-
sql: Joi.func().required(),
655-
label: Joi.alternatives([
656-
Joi.string(),
657-
Joi.object().keys({
658-
sql: Joi.func().required()
659-
})
660-
])
661-
})),
662-
else: Joi.object().keys({
663-
label: Joi.alternatives([
664-
Joi.string(),
665-
Joi.object().keys({
666-
sql: Joi.func().required()
667-
})
668-
])
669-
})
670-
}).required()
671-
}),
672-
inherit(BaseDimensionWithoutSubQuery, {
673-
latitude: Joi.object().keys({
674-
sql: Joi.func().required()
675-
}).required(),
676-
longitude: Joi.object().keys({
677-
sql: Joi.func().required()
678-
}).required()
679-
}),
680-
inherit(BaseDimension, {
681-
sql: Joi.func().required(),
682-
}),
683-
inherit(BaseDimension, {
684-
multiStage: Joi.boolean().valid(true),
685-
type: Joi.any().valid('number').required(),
686-
sql: Joi.func().required(),
687-
addGroupBy: Joi.func(),
688-
}),
689-
// TODO should be valid only for calendar cubes, but this requires significant refactoring
690-
// of all schemas. Left for the future when we'll switch to zod.
691-
inherit(BaseDimensionWithoutSubQuery, {
692-
type: Joi.any().valid('time').required(),
693-
sql: Joi.func().required(),
694-
timeShift: Joi.array().items(CalendarTimeShiftItem),
695-
})
696-
));
655+
const SwitchDimension = Joi.object({
656+
type: Joi.string().valid('switch').required(),
657+
values: Joi.array().items(Joi.string()).min(1).required()
658+
});
659+
660+
const DimensionsSchema = Joi.object().pattern(identifierRegex, Joi.alternatives().conditional(Joi.ref('.type'), {
661+
is: 'switch',
662+
then: SwitchDimension,
663+
otherwise: Joi.alternatives().try(
664+
inherit(BaseDimensionWithoutSubQuery, {
665+
case: Joi.object().keys({
666+
when: Joi.array().items(Joi.object().keys({
667+
sql: Joi.func().required(),
668+
label: Joi.alternatives([
669+
Joi.string(),
670+
Joi.object().keys({
671+
sql: Joi.func().required()
672+
})
673+
])
674+
})),
675+
else: Joi.object().keys({
676+
label: Joi.alternatives([
677+
Joi.string(),
678+
Joi.object().keys({
679+
sql: Joi.func().required()
680+
})
681+
])
682+
})
683+
}).required()
684+
}),
685+
inherit(BaseDimensionWithoutSubQuery, {
686+
latitude: Joi.object().keys({
687+
sql: Joi.func().required()
688+
}).required(),
689+
longitude: Joi.object().keys({
690+
sql: Joi.func().required()
691+
}).required()
692+
}),
693+
inherit(BaseDimension, {
694+
sql: Joi.func().required(),
695+
}),
696+
inherit(BaseDimension, {
697+
multiStage: Joi.boolean().valid(true),
698+
type: Joi.any().valid('number').required(),
699+
sql: Joi.func().required(),
700+
addGroupBy: Joi.func(),
701+
}),
702+
// TODO should be valid only for calendar cubes, but this requires significant refactoring
703+
// of all schemas. Left for the future when we'll switch to zod.
704+
inherit(BaseDimensionWithoutSubQuery, {
705+
type: Joi.any().valid('time').required(),
706+
sql: Joi.func().required(),
707+
timeShift: Joi.array().items(CalendarTimeShiftItem),
708+
})
709+
)
710+
}));
697711

698712
const SegmentsSchema = Joi.object().pattern(identifierRegex, Joi.object().keys({
699713
aliases: Joi.array().items(Joi.string()),

0 commit comments

Comments
 (0)