@cubejs-backend/schema-compiler 0.34.29 → 0.34.31
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/AWSElasticSearchQuery.d.ts +1 -6
- package/dist/src/adapter/AWSElasticSearchQuery.d.ts.map +1 -1
- package/dist/src/adapter/BaseDimension.d.ts +17 -15
- package/dist/src/adapter/BaseDimension.d.ts.map +1 -1
- package/dist/src/adapter/BaseDimension.js +3 -2
- package/dist/src/adapter/BaseDimension.js.map +1 -1
- package/dist/src/adapter/BaseFilter.d.ts +33 -26
- package/dist/src/adapter/BaseFilter.d.ts.map +1 -1
- package/dist/src/adapter/BaseFilter.js +1 -2
- package/dist/src/adapter/BaseFilter.js.map +1 -1
- package/dist/src/adapter/BaseGroupFilter.d.ts +5 -5
- 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 +19 -15
- package/dist/src/adapter/BaseMeasure.d.ts.map +1 -1
- package/dist/src/adapter/BaseMeasure.js +2 -1
- package/dist/src/adapter/BaseMeasure.js.map +1 -1
- package/dist/src/adapter/BaseQuery.d.ts +11 -11
- package/dist/src/adapter/BaseQuery.d.ts.map +1 -1
- package/dist/src/adapter/BaseQuery.js +7 -7
- package/dist/src/adapter/BaseQuery.js.map +1 -1
- package/dist/src/adapter/BaseSegment.d.ts +8 -7
- package/dist/src/adapter/BaseSegment.d.ts.map +1 -1
- package/dist/src/adapter/BaseSegment.js.map +1 -1
- package/dist/src/adapter/BaseTimeDimension.d.ts +27 -20
- package/dist/src/adapter/BaseTimeDimension.d.ts.map +1 -1
- package/dist/src/adapter/BaseTimeDimension.js +7 -2
- package/dist/src/adapter/BaseTimeDimension.js.map +1 -1
- package/dist/src/adapter/BigqueryQuery.d.ts +1 -8
- package/dist/src/adapter/BigqueryQuery.d.ts.map +1 -1
- package/dist/src/adapter/ClickHouseQuery.d.ts +1 -7
- package/dist/src/adapter/ClickHouseQuery.d.ts.map +1 -1
- package/dist/src/adapter/CubeStoreQuery.d.ts +1 -5
- package/dist/src/adapter/CubeStoreQuery.d.ts.map +1 -1
- package/dist/src/adapter/ElasticSearchQuery.d.ts +1 -6
- package/dist/src/adapter/ElasticSearchQuery.d.ts.map +1 -1
- package/dist/src/adapter/HiveQuery.d.ts +1 -6
- package/dist/src/adapter/HiveQuery.d.ts.map +1 -1
- package/dist/src/adapter/MssqlQuery.d.ts +1 -6
- package/dist/src/adapter/MssqlQuery.d.ts.map +1 -1
- package/dist/src/adapter/MysqlQuery.d.ts +1 -6
- package/dist/src/adapter/MysqlQuery.d.ts.map +1 -1
- package/dist/src/adapter/OracleQuery.d.ts +1 -10
- package/dist/src/adapter/OracleQuery.d.ts.map +1 -1
- package/dist/src/adapter/ParamAllocator.d.ts +1 -0
- package/dist/src/adapter/ParamAllocator.d.ts.map +1 -1
- package/dist/src/adapter/ParamAllocator.js +3 -0
- package/dist/src/adapter/ParamAllocator.js.map +1 -1
- package/dist/src/adapter/PrestodbQuery.d.ts +1 -7
- package/dist/src/adapter/PrestodbQuery.d.ts.map +1 -1
- package/dist/src/adapter/SqliteQuery.d.ts +1 -6
- package/dist/src/adapter/SqliteQuery.d.ts.map +1 -1
- package/dist/src/compiler/ContextEvaluator.d.ts +5 -2
- package/dist/src/compiler/ContextEvaluator.d.ts.map +1 -1
- package/dist/src/compiler/ContextEvaluator.js +3 -0
- package/dist/src/compiler/ContextEvaluator.js.map +1 -1
- package/dist/src/compiler/CubeEvaluator.d.ts +90 -62
- package/dist/src/compiler/CubeEvaluator.d.ts.map +1 -1
- package/dist/src/compiler/CubeEvaluator.js +21 -37
- package/dist/src/compiler/CubeEvaluator.js.map +1 -1
- package/dist/src/compiler/CubeToMetaTransformer.d.ts +16 -9
- package/dist/src/compiler/CubeToMetaTransformer.d.ts.map +1 -1
- package/dist/src/compiler/CubeToMetaTransformer.js +7 -0
- package/dist/src/compiler/CubeToMetaTransformer.js.map +1 -1
- package/dist/src/compiler/CubeValidator.d.ts +11 -9
- package/dist/src/compiler/CubeValidator.d.ts.map +1 -1
- package/dist/src/compiler/CubeValidator.js +237 -226
- package/dist/src/compiler/CubeValidator.js.map +1 -1
- package/dist/src/compiler/JoinGraph.d.ts +7 -3
- package/dist/src/compiler/JoinGraph.d.ts.map +1 -1
- package/dist/src/compiler/JoinGraph.js +9 -0
- package/dist/src/compiler/JoinGraph.js.map +1 -1
- package/package.json +4 -4
- package/dist/src/compiler/ErrorHandler.d.ts +0 -2
- package/dist/src/compiler/ErrorHandler.d.ts.map +0 -1
- package/dist/src/compiler/ErrorHandler.js +0 -23
- package/dist/src/compiler/ErrorHandler.js.map +0 -1
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.CubeValidator = exports.functionFieldsPatterns = exports.nonStringFields = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
7
|
+
const joi_1 = __importDefault(require("joi"));
|
|
8
|
+
const cron_parser_1 = __importDefault(require("cron-parser"));
|
|
6
9
|
/* *****************************
|
|
7
10
|
* ATTENTION:
|
|
8
11
|
* In case of adding/removing/changing any Joi.func() field that needs to be transpiled,
|
|
@@ -26,99 +29,107 @@ exports.nonStringFields = new Set([
|
|
|
26
29
|
'prefix'
|
|
27
30
|
]);
|
|
28
31
|
const identifierRegex = /^[_a-zA-Z][_a-zA-Z0-9]*$/;
|
|
29
|
-
const identifier =
|
|
30
|
-
|
|
32
|
+
const identifier = joi_1.default.string().regex(identifierRegex, 'identifier');
|
|
33
|
+
function formatStatePath(state) {
|
|
34
|
+
if (state.path) {
|
|
35
|
+
// TODO: Remove cast after upgrade of Joi. It show it as string, while it's array
|
|
36
|
+
const path = state.path;
|
|
37
|
+
return path.join('.');
|
|
38
|
+
}
|
|
39
|
+
return '<unknown path>';
|
|
40
|
+
}
|
|
41
|
+
const regexTimeInterval = joi_1.default.string().custom((value, helper) => {
|
|
31
42
|
if (value.match(/^(-?\d+) (minute|hour|day|week|month|quarter|year)$/)) {
|
|
32
43
|
return value;
|
|
33
44
|
}
|
|
34
45
|
else {
|
|
35
|
-
return helper.message({ custom: `(${helper.state
|
|
46
|
+
return helper.message({ custom: `(${formatStatePath(helper.state)} = ${value}) does not match regexp: /^(-?\\d+) (minute|hour|day|week|month|quarter|year)$/` });
|
|
36
47
|
}
|
|
37
48
|
});
|
|
38
|
-
const timeInterval =
|
|
49
|
+
const timeInterval = joi_1.default.alternatives([
|
|
39
50
|
regexTimeInterval,
|
|
40
|
-
|
|
51
|
+
joi_1.default.any().valid('unbounded')
|
|
41
52
|
]);
|
|
42
|
-
const everyInterval =
|
|
53
|
+
const everyInterval = joi_1.default.string().custom((value, helper) => {
|
|
43
54
|
if (value.match(/^(\d+) (second|minute|hour|day|week)s?$/)) {
|
|
44
55
|
return value;
|
|
45
56
|
}
|
|
46
57
|
else {
|
|
47
|
-
return helper.message({ custom: `(${helper.state
|
|
58
|
+
return helper.message({ custom: `(${formatStatePath(helper.state)} = ${value}) does not match regexp: /^(\\d+) (second|minute|hour|day|week)s?$/` });
|
|
48
59
|
}
|
|
49
60
|
});
|
|
50
|
-
const everyCronInterval =
|
|
61
|
+
const everyCronInterval = joi_1.default.string().custom((value, helper) => {
|
|
51
62
|
try {
|
|
52
|
-
|
|
63
|
+
cron_parser_1.default.parseExpression(value);
|
|
53
64
|
return value;
|
|
54
65
|
}
|
|
55
66
|
catch (e) {
|
|
56
|
-
return helper.message({ custom: `(${helper.state
|
|
67
|
+
return helper.message({ custom: `(${formatStatePath(helper.state)} = ${value}) CronParser: ${e.toString()}` });
|
|
57
68
|
}
|
|
58
69
|
});
|
|
59
|
-
const everyCronTimeZone =
|
|
70
|
+
const everyCronTimeZone = joi_1.default.string().custom((value, helper) => {
|
|
60
71
|
try {
|
|
61
|
-
|
|
72
|
+
cron_parser_1.default.parseExpression('0 * * * *', { currentDate: '2020-01-01 00:00:01', tz: value });
|
|
62
73
|
return value;
|
|
63
74
|
}
|
|
64
75
|
catch (e) {
|
|
65
|
-
return helper.message({ custom: `(${helper.state
|
|
76
|
+
return helper.message({ custom: `(${formatStatePath(helper.state)} = ${value}) unknown timezone. Take a look here https://cube.dev/docs/schema/reference/cube#supported-timezones to get available time zones` });
|
|
66
77
|
}
|
|
67
78
|
});
|
|
68
79
|
const BaseDimensionWithoutSubQuery = {
|
|
69
|
-
aliases:
|
|
70
|
-
type:
|
|
71
|
-
fieldType:
|
|
72
|
-
valuesAsSegments:
|
|
73
|
-
primaryKey:
|
|
74
|
-
shown:
|
|
75
|
-
public:
|
|
76
|
-
title:
|
|
77
|
-
description:
|
|
78
|
-
suggestFilterValues:
|
|
79
|
-
enableSuggestions:
|
|
80
|
-
format:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
type:
|
|
84
|
-
label:
|
|
80
|
+
aliases: joi_1.default.array().items(joi_1.default.string()),
|
|
81
|
+
type: joi_1.default.any().valid('string', 'number', 'boolean', 'time', 'geo').required(),
|
|
82
|
+
fieldType: joi_1.default.any().valid('string'),
|
|
83
|
+
valuesAsSegments: joi_1.default.boolean().strict(),
|
|
84
|
+
primaryKey: joi_1.default.boolean().strict(),
|
|
85
|
+
shown: joi_1.default.boolean().strict(),
|
|
86
|
+
public: joi_1.default.boolean().strict(),
|
|
87
|
+
title: joi_1.default.string(),
|
|
88
|
+
description: joi_1.default.string(),
|
|
89
|
+
suggestFilterValues: joi_1.default.boolean().strict(),
|
|
90
|
+
enableSuggestions: joi_1.default.boolean().strict(),
|
|
91
|
+
format: joi_1.default.alternatives([
|
|
92
|
+
joi_1.default.string().valid('imageUrl', 'link', 'currency', 'percent', 'number', 'id'),
|
|
93
|
+
joi_1.default.object().keys({
|
|
94
|
+
type: joi_1.default.string().valid('link'),
|
|
95
|
+
label: joi_1.default.string().required()
|
|
85
96
|
})
|
|
86
97
|
]),
|
|
87
|
-
meta:
|
|
98
|
+
meta: joi_1.default.any()
|
|
88
99
|
};
|
|
89
100
|
const BaseDimension = Object.assign({
|
|
90
|
-
subQuery:
|
|
91
|
-
propagateFiltersToSubQuery:
|
|
101
|
+
subQuery: joi_1.default.boolean().strict(),
|
|
102
|
+
propagateFiltersToSubQuery: joi_1.default.boolean().strict()
|
|
92
103
|
}, BaseDimensionWithoutSubQuery);
|
|
93
104
|
const BaseMeasure = {
|
|
94
|
-
aliases:
|
|
95
|
-
format:
|
|
96
|
-
public:
|
|
105
|
+
aliases: joi_1.default.array().items(joi_1.default.string()),
|
|
106
|
+
format: joi_1.default.any().valid('percent', 'currency', 'number'),
|
|
107
|
+
public: joi_1.default.boolean().strict(),
|
|
97
108
|
// TODO: Deprecate and remove, please use public
|
|
98
|
-
visible:
|
|
109
|
+
visible: joi_1.default.boolean().strict(),
|
|
99
110
|
// TODO: Deprecate and remove, please use public
|
|
100
|
-
shown:
|
|
101
|
-
cumulative:
|
|
102
|
-
filters:
|
|
103
|
-
sql:
|
|
111
|
+
shown: joi_1.default.boolean().strict(),
|
|
112
|
+
cumulative: joi_1.default.boolean().strict(),
|
|
113
|
+
filters: joi_1.default.array().items(joi_1.default.object().keys({
|
|
114
|
+
sql: joi_1.default.func().required()
|
|
104
115
|
})),
|
|
105
|
-
title:
|
|
106
|
-
description:
|
|
107
|
-
rollingWindow:
|
|
116
|
+
title: joi_1.default.string(),
|
|
117
|
+
description: joi_1.default.string(),
|
|
118
|
+
rollingWindow: joi_1.default.object().keys({
|
|
108
119
|
trailing: timeInterval,
|
|
109
120
|
leading: timeInterval,
|
|
110
|
-
offset:
|
|
121
|
+
offset: joi_1.default.any().valid('start', 'end')
|
|
111
122
|
}),
|
|
112
|
-
drillMemberReferences:
|
|
113
|
-
drillMembers:
|
|
114
|
-
drillFilters:
|
|
115
|
-
sql:
|
|
123
|
+
drillMemberReferences: joi_1.default.func(),
|
|
124
|
+
drillMembers: joi_1.default.func(),
|
|
125
|
+
drillFilters: joi_1.default.array().items(joi_1.default.object().keys({
|
|
126
|
+
sql: joi_1.default.func().required()
|
|
116
127
|
})),
|
|
117
|
-
meta:
|
|
128
|
+
meta: joi_1.default.any()
|
|
118
129
|
};
|
|
119
130
|
function condition(fun, then, otherwise) {
|
|
120
|
-
return
|
|
121
|
-
is:
|
|
131
|
+
return joi_1.default.alternatives().conditional(joi_1.default.ref('.'), {
|
|
132
|
+
is: joi_1.default.custom((value, helper) => (fun(value) ? value : helper.message({}))),
|
|
122
133
|
then,
|
|
123
134
|
otherwise
|
|
124
135
|
});
|
|
@@ -127,223 +138,223 @@ function defined(a) {
|
|
|
127
138
|
return typeof a !== 'undefined';
|
|
128
139
|
}
|
|
129
140
|
function inherit(a, b) {
|
|
130
|
-
return
|
|
141
|
+
return joi_1.default.object().keys(Object.assign({}, a, b));
|
|
131
142
|
}
|
|
132
143
|
function requireOneOf(...keys) {
|
|
133
|
-
return
|
|
144
|
+
return joi_1.default.alternatives().try(...(keys.map((k) => joi_1.default.object().keys({ [k]: joi_1.default.exist().required() }))));
|
|
134
145
|
}
|
|
135
|
-
const PreAggregationRefreshKeySchema = condition((s) => defined(s.sql),
|
|
136
|
-
sql:
|
|
146
|
+
const PreAggregationRefreshKeySchema = condition((s) => defined(s.sql), joi_1.default.object().keys({
|
|
147
|
+
sql: joi_1.default.func().required(),
|
|
137
148
|
// We dont support timezone for this, because it's useless
|
|
138
149
|
// We cannot support cron interval
|
|
139
150
|
every: everyInterval,
|
|
140
|
-
}), condition((s) => defined(s.every),
|
|
141
|
-
every:
|
|
151
|
+
}), condition((s) => defined(s.every), joi_1.default.object().keys({
|
|
152
|
+
every: joi_1.default.alternatives().try(everyInterval, everyCronInterval),
|
|
142
153
|
timezone: everyCronTimeZone,
|
|
143
|
-
incremental:
|
|
154
|
+
incremental: joi_1.default.boolean().strict(),
|
|
144
155
|
updateWindow: everyInterval
|
|
145
156
|
}), requireOneOf('sql', 'every')));
|
|
146
157
|
const BasePreAggregationWithoutPartitionGranularity = {
|
|
147
158
|
refreshKey: PreAggregationRefreshKeySchema,
|
|
148
|
-
sqlAlias:
|
|
149
|
-
useOriginalSqlPreAggregations:
|
|
150
|
-
external:
|
|
151
|
-
scheduledRefresh:
|
|
152
|
-
indexes:
|
|
153
|
-
sql:
|
|
154
|
-
}),
|
|
155
|
-
columns:
|
|
156
|
-
type:
|
|
159
|
+
sqlAlias: joi_1.default.string().optional(),
|
|
160
|
+
useOriginalSqlPreAggregations: joi_1.default.boolean().strict(),
|
|
161
|
+
external: joi_1.default.boolean().strict(),
|
|
162
|
+
scheduledRefresh: joi_1.default.boolean().strict(),
|
|
163
|
+
indexes: joi_1.default.object().pattern(identifierRegex, joi_1.default.alternatives().try(joi_1.default.object().keys({
|
|
164
|
+
sql: joi_1.default.func().required()
|
|
165
|
+
}), joi_1.default.object().keys({
|
|
166
|
+
columns: joi_1.default.func().required(),
|
|
167
|
+
type: joi_1.default.any().valid('regular', 'aggregate'),
|
|
157
168
|
}))),
|
|
158
169
|
// refreshRange was deprecated
|
|
159
170
|
refreshRangeStart: {
|
|
160
|
-
sql:
|
|
171
|
+
sql: joi_1.default.func().required()
|
|
161
172
|
},
|
|
162
173
|
refreshRangeEnd: {
|
|
163
|
-
sql:
|
|
174
|
+
sql: joi_1.default.func().required()
|
|
164
175
|
},
|
|
165
176
|
// new api
|
|
166
177
|
buildRangeStart: {
|
|
167
|
-
sql:
|
|
178
|
+
sql: joi_1.default.func().required()
|
|
168
179
|
},
|
|
169
180
|
buildRangeEnd: {
|
|
170
|
-
sql:
|
|
181
|
+
sql: joi_1.default.func().required()
|
|
171
182
|
},
|
|
172
|
-
readOnly:
|
|
173
|
-
streamOffset:
|
|
183
|
+
readOnly: joi_1.default.boolean().strict(),
|
|
184
|
+
streamOffset: joi_1.default.any().valid('earliest', 'latest'),
|
|
174
185
|
};
|
|
175
186
|
const BasePreAggregation = {
|
|
176
187
|
...BasePreAggregationWithoutPartitionGranularity,
|
|
177
|
-
partitionGranularity:
|
|
188
|
+
partitionGranularity: joi_1.default.any().valid('hour', 'day', 'week', 'month', 'quarter', 'year'),
|
|
178
189
|
};
|
|
179
190
|
const AutoRollupSchema = inherit(BasePreAggregation, {
|
|
180
|
-
type:
|
|
181
|
-
maxPreAggregations:
|
|
191
|
+
type: joi_1.default.any().valid('autoRollup').required(),
|
|
192
|
+
maxPreAggregations: joi_1.default.number(),
|
|
182
193
|
});
|
|
183
194
|
const OriginalSqlSchema = condition((s) => defined(s.partitionGranularity) || defined(s.timeDimension) || defined(s.timeDimensionReference), condition((s) => defined(s.timeDimensionReference), inherit(BasePreAggregation, {
|
|
184
|
-
type:
|
|
185
|
-
uniqueKeyColumns:
|
|
195
|
+
type: joi_1.default.any().valid('originalSql').required(),
|
|
196
|
+
uniqueKeyColumns: joi_1.default.array().items(joi_1.default.string()),
|
|
186
197
|
partitionGranularity: BasePreAggregation.partitionGranularity.required(),
|
|
187
|
-
timeDimensionReference:
|
|
188
|
-
allowNonStrictDateRangeMatch:
|
|
198
|
+
timeDimensionReference: joi_1.default.func().required(),
|
|
199
|
+
allowNonStrictDateRangeMatch: joi_1.default.bool(),
|
|
189
200
|
}), inherit(BasePreAggregation, {
|
|
190
|
-
type:
|
|
191
|
-
uniqueKeyColumns:
|
|
201
|
+
type: joi_1.default.any().valid('originalSql').required(),
|
|
202
|
+
uniqueKeyColumns: joi_1.default.array().items(joi_1.default.string()),
|
|
192
203
|
partitionGranularity: BasePreAggregation.partitionGranularity.required(),
|
|
193
|
-
timeDimension:
|
|
194
|
-
allowNonStrictDateRangeMatch:
|
|
204
|
+
timeDimension: joi_1.default.func().required(),
|
|
205
|
+
allowNonStrictDateRangeMatch: joi_1.default.bool(),
|
|
195
206
|
})), inherit(BasePreAggregationWithoutPartitionGranularity, {
|
|
196
|
-
type:
|
|
197
|
-
uniqueKeyColumns:
|
|
207
|
+
type: joi_1.default.any().valid('originalSql').required(),
|
|
208
|
+
uniqueKeyColumns: joi_1.default.array().items(joi_1.default.string())
|
|
198
209
|
}));
|
|
199
|
-
const GranularitySchema =
|
|
210
|
+
const GranularitySchema = joi_1.default.string().valid('second', 'minute', 'hour', 'day', 'week', 'month', 'quarter', 'year').required();
|
|
200
211
|
const ReferencesFields = ['timeDimensionReference', 'rollupReferences', 'measureReferences', 'dimensionReferences', 'segmentReferences'];
|
|
201
212
|
const NonReferencesFields = ['timeDimension', 'rollups', 'measures', 'dimensions', 'segments'];
|
|
202
213
|
function hasAnyField(fields, s) {
|
|
203
214
|
return !fields.every((f) => !defined(s[f]));
|
|
204
215
|
}
|
|
205
216
|
function errorOnMixing(schema) {
|
|
206
|
-
return condition((s) => hasAnyField(ReferencesFields, s) && hasAnyField(NonReferencesFields, s),
|
|
217
|
+
return condition((s) => hasAnyField(ReferencesFields, s) && hasAnyField(NonReferencesFields, s), joi_1.default.any().forbidden().error(new Error(`[${ReferencesFields.join(', ')}] are deprecated, please, use [${NonReferencesFields.join(', ')}] instead`)), schema);
|
|
207
218
|
}
|
|
208
219
|
const RollUpJoinSchema = condition((s) => defined(s.granularity) || defined(s.timeDimension) || defined(s.timeDimensionReference), condition((s) => defined(s.rollupReferences) || defined(s.timeDimensionReference), inherit(BasePreAggregation, {
|
|
209
|
-
type:
|
|
210
|
-
scheduledRefresh:
|
|
220
|
+
type: joi_1.default.any().valid('rollupJoin').required(),
|
|
221
|
+
scheduledRefresh: joi_1.default.boolean().valid(false),
|
|
211
222
|
granularity: GranularitySchema,
|
|
212
|
-
allowNonStrictDateRangeMatch:
|
|
213
|
-
timeDimensionReference:
|
|
214
|
-
rollupReferences:
|
|
215
|
-
measureReferences:
|
|
216
|
-
dimensionReferences:
|
|
217
|
-
segmentReferences:
|
|
223
|
+
allowNonStrictDateRangeMatch: joi_1.default.bool(),
|
|
224
|
+
timeDimensionReference: joi_1.default.func().required(),
|
|
225
|
+
rollupReferences: joi_1.default.func().required(),
|
|
226
|
+
measureReferences: joi_1.default.func(),
|
|
227
|
+
dimensionReferences: joi_1.default.func(),
|
|
228
|
+
segmentReferences: joi_1.default.func(),
|
|
218
229
|
}),
|
|
219
230
|
// RollupJoin without references
|
|
220
231
|
inherit(BasePreAggregation, {
|
|
221
|
-
type:
|
|
222
|
-
scheduledRefresh:
|
|
232
|
+
type: joi_1.default.any().valid('rollupJoin').required(),
|
|
233
|
+
scheduledRefresh: joi_1.default.boolean().valid(false),
|
|
223
234
|
granularity: GranularitySchema,
|
|
224
|
-
timeDimension:
|
|
225
|
-
allowNonStrictDateRangeMatch:
|
|
226
|
-
rollups:
|
|
227
|
-
measures:
|
|
228
|
-
dimensions:
|
|
229
|
-
segments:
|
|
235
|
+
timeDimension: joi_1.default.func().required(),
|
|
236
|
+
allowNonStrictDateRangeMatch: joi_1.default.bool(),
|
|
237
|
+
rollups: joi_1.default.func().required(),
|
|
238
|
+
measures: joi_1.default.func(),
|
|
239
|
+
dimensions: joi_1.default.func(),
|
|
240
|
+
segments: joi_1.default.func(),
|
|
230
241
|
})), condition((s) => defined(s.rollupReferences), inherit(BasePreAggregation, {
|
|
231
|
-
type:
|
|
232
|
-
scheduledRefresh:
|
|
233
|
-
rollupReferences:
|
|
234
|
-
measureReferences:
|
|
235
|
-
dimensionReferences:
|
|
236
|
-
segmentReferences:
|
|
242
|
+
type: joi_1.default.any().valid('rollupJoin').required(),
|
|
243
|
+
scheduledRefresh: joi_1.default.boolean().valid(false),
|
|
244
|
+
rollupReferences: joi_1.default.func().required(),
|
|
245
|
+
measureReferences: joi_1.default.func(),
|
|
246
|
+
dimensionReferences: joi_1.default.func(),
|
|
247
|
+
segmentReferences: joi_1.default.func(),
|
|
237
248
|
}),
|
|
238
249
|
// RollupJoin without references
|
|
239
250
|
condition((s) => defined(s.rollups), inherit(BasePreAggregation, {
|
|
240
|
-
type:
|
|
241
|
-
scheduledRefresh:
|
|
242
|
-
rollups:
|
|
243
|
-
measures:
|
|
244
|
-
dimensions:
|
|
245
|
-
segments:
|
|
251
|
+
type: joi_1.default.any().valid('rollupJoin').required(),
|
|
252
|
+
scheduledRefresh: joi_1.default.boolean().valid(false),
|
|
253
|
+
rollups: joi_1.default.func().required(),
|
|
254
|
+
measures: joi_1.default.func(),
|
|
255
|
+
dimensions: joi_1.default.func(),
|
|
256
|
+
segments: joi_1.default.func(),
|
|
246
257
|
}), requireOneOf('granularity', 'rollups', 'timeDimension'))));
|
|
247
258
|
const RollupLambdaSchema = condition((s) => defined(s.granularity) || defined(s.timeDimension), {
|
|
248
|
-
type:
|
|
259
|
+
type: joi_1.default.any().valid('rollupLambda').required(),
|
|
249
260
|
granularity: GranularitySchema,
|
|
250
|
-
timeDimension:
|
|
251
|
-
rollups:
|
|
252
|
-
measures:
|
|
253
|
-
dimensions:
|
|
254
|
-
segments:
|
|
255
|
-
unionWithSourceData:
|
|
261
|
+
timeDimension: joi_1.default.func().required(),
|
|
262
|
+
rollups: joi_1.default.func().required(),
|
|
263
|
+
measures: joi_1.default.func(),
|
|
264
|
+
dimensions: joi_1.default.func(),
|
|
265
|
+
segments: joi_1.default.func(),
|
|
266
|
+
unionWithSourceData: joi_1.default.boolean().strict(),
|
|
256
267
|
}, {
|
|
257
|
-
type:
|
|
258
|
-
rollups:
|
|
259
|
-
measures:
|
|
260
|
-
dimensions:
|
|
261
|
-
segments:
|
|
262
|
-
unionWithSourceData:
|
|
268
|
+
type: joi_1.default.any().valid('rollupLambda').required(),
|
|
269
|
+
rollups: joi_1.default.func().required(),
|
|
270
|
+
measures: joi_1.default.func(),
|
|
271
|
+
dimensions: joi_1.default.func(),
|
|
272
|
+
segments: joi_1.default.func(),
|
|
273
|
+
unionWithSourceData: joi_1.default.boolean().strict(),
|
|
263
274
|
});
|
|
264
275
|
const RollUpSchema = condition((s) => defined(s.granularity) || defined(s.timeDimension) || defined(s.timeDimensionReference), condition((s) => defined(s.timeDimensionReference), inherit(BasePreAggregation, {
|
|
265
|
-
type:
|
|
266
|
-
timeDimensionReference:
|
|
276
|
+
type: joi_1.default.any().valid('rollup').required(),
|
|
277
|
+
timeDimensionReference: joi_1.default.func().required(),
|
|
267
278
|
granularity: GranularitySchema,
|
|
268
|
-
allowNonStrictDateRangeMatch:
|
|
269
|
-
measureReferences:
|
|
270
|
-
dimensionReferences:
|
|
271
|
-
segmentReferences:
|
|
279
|
+
allowNonStrictDateRangeMatch: joi_1.default.bool(),
|
|
280
|
+
measureReferences: joi_1.default.func(),
|
|
281
|
+
dimensionReferences: joi_1.default.func(),
|
|
282
|
+
segmentReferences: joi_1.default.func(),
|
|
272
283
|
}),
|
|
273
284
|
// Rollup without References postfix
|
|
274
285
|
inherit(BasePreAggregation, {
|
|
275
|
-
type:
|
|
276
|
-
timeDimension:
|
|
277
|
-
allowNonStrictDateRangeMatch:
|
|
286
|
+
type: joi_1.default.any().valid('rollup').required(),
|
|
287
|
+
timeDimension: joi_1.default.func().required(),
|
|
288
|
+
allowNonStrictDateRangeMatch: joi_1.default.bool(),
|
|
278
289
|
granularity: GranularitySchema,
|
|
279
|
-
measures:
|
|
280
|
-
dimensions:
|
|
281
|
-
segments:
|
|
282
|
-
})),
|
|
283
|
-
type:
|
|
284
|
-
measureReferences:
|
|
285
|
-
dimensionReferences:
|
|
286
|
-
segmentReferences:
|
|
290
|
+
measures: joi_1.default.func(),
|
|
291
|
+
dimensions: joi_1.default.func(),
|
|
292
|
+
segments: joi_1.default.func(),
|
|
293
|
+
})), joi_1.default.alternatives().try(inherit(BasePreAggregation, {
|
|
294
|
+
type: joi_1.default.any().valid('rollup').required(),
|
|
295
|
+
measureReferences: joi_1.default.func(),
|
|
296
|
+
dimensionReferences: joi_1.default.func(),
|
|
297
|
+
segmentReferences: joi_1.default.func()
|
|
287
298
|
}),
|
|
288
299
|
// Rollup without References postfix
|
|
289
300
|
inherit(BasePreAggregation, {
|
|
290
|
-
type:
|
|
291
|
-
measures:
|
|
292
|
-
dimensions:
|
|
293
|
-
segments:
|
|
301
|
+
type: joi_1.default.any().valid('rollup').required(),
|
|
302
|
+
measures: joi_1.default.func(),
|
|
303
|
+
dimensions: joi_1.default.func(),
|
|
304
|
+
segments: joi_1.default.func()
|
|
294
305
|
})));
|
|
295
|
-
const PreAggregationsAlternatives =
|
|
306
|
+
const PreAggregationsAlternatives = joi_1.default.object().pattern(identifierRegex, errorOnMixing(joi_1.default.alternatives().conditional(joi_1.default.ref('.type'), [
|
|
296
307
|
{ is: 'autoRollup', then: AutoRollupSchema },
|
|
297
308
|
{ is: 'originalSql', then: OriginalSqlSchema },
|
|
298
309
|
{ is: 'rollupJoin', then: RollUpJoinSchema },
|
|
299
310
|
{ is: 'rollupLambda', then: RollupLambdaSchema },
|
|
300
311
|
{ is: 'rollup',
|
|
301
312
|
then: RollUpSchema,
|
|
302
|
-
otherwise:
|
|
303
|
-
type:
|
|
313
|
+
otherwise: joi_1.default.object().keys({
|
|
314
|
+
type: joi_1.default.string().valid('autoRollup', 'originalSql', 'rollupJoin', 'rollup').required()
|
|
304
315
|
})
|
|
305
316
|
}
|
|
306
317
|
])));
|
|
307
|
-
const CubeRefreshKeySchema = condition((s) => defined(s.every), condition((s) => defined(s.sql),
|
|
308
|
-
sql:
|
|
318
|
+
const CubeRefreshKeySchema = condition((s) => defined(s.every), condition((s) => defined(s.sql), joi_1.default.object().keys({
|
|
319
|
+
sql: joi_1.default.func().required(),
|
|
309
320
|
// We dont support timezone for this, because it's useless
|
|
310
321
|
// We cannot support cron interval
|
|
311
322
|
every: everyInterval,
|
|
312
|
-
}),
|
|
313
|
-
every:
|
|
323
|
+
}), joi_1.default.object().keys({
|
|
324
|
+
every: joi_1.default.alternatives().try(everyInterval, everyCronInterval).required(),
|
|
314
325
|
timezone: everyCronTimeZone,
|
|
315
|
-
})), condition((s) => defined(s.immutable),
|
|
316
|
-
immutable:
|
|
326
|
+
})), condition((s) => defined(s.immutable), joi_1.default.object().keys({
|
|
327
|
+
immutable: joi_1.default.boolean().strict().required()
|
|
317
328
|
}), requireOneOf('every', 'sql', 'immutable')));
|
|
318
|
-
const measureType =
|
|
319
|
-
const measureTypeWithCount =
|
|
320
|
-
const MeasuresSchema =
|
|
329
|
+
const measureType = joi_1.default.string().valid('number', 'string', 'boolean', 'time', 'sum', 'avg', 'min', 'max', 'countDistinct', 'runningTotal', 'countDistinctApprox');
|
|
330
|
+
const measureTypeWithCount = joi_1.default.string().valid('count', 'number', 'string', 'boolean', 'time', 'sum', 'avg', 'min', 'max', 'countDistinct', 'runningTotal', 'countDistinctApprox');
|
|
331
|
+
const MeasuresSchema = joi_1.default.object().pattern(identifierRegex, joi_1.default.alternatives().conditional(joi_1.default.ref('.type'), [
|
|
321
332
|
{
|
|
322
333
|
is: 'count',
|
|
323
334
|
then: inherit(BaseMeasure, {
|
|
324
|
-
type:
|
|
325
|
-
sql:
|
|
335
|
+
type: joi_1.default.any().valid('count').required(),
|
|
336
|
+
sql: joi_1.default.func(),
|
|
326
337
|
})
|
|
327
338
|
},
|
|
328
339
|
{
|
|
329
340
|
is: measureType,
|
|
330
341
|
then: inherit(BaseMeasure, {
|
|
331
|
-
sql:
|
|
342
|
+
sql: joi_1.default.func().required(),
|
|
332
343
|
type: measureType.required()
|
|
333
344
|
}),
|
|
334
|
-
otherwise:
|
|
345
|
+
otherwise: joi_1.default.object().keys({
|
|
335
346
|
type: measureTypeWithCount.required()
|
|
336
347
|
})
|
|
337
348
|
}
|
|
338
349
|
]));
|
|
339
|
-
const SegmentsSchema =
|
|
340
|
-
aliases:
|
|
341
|
-
sql:
|
|
342
|
-
title:
|
|
343
|
-
description:
|
|
344
|
-
meta:
|
|
345
|
-
shown:
|
|
346
|
-
public:
|
|
350
|
+
const SegmentsSchema = joi_1.default.object().pattern(identifierRegex, joi_1.default.object().keys({
|
|
351
|
+
aliases: joi_1.default.array().items(joi_1.default.string()),
|
|
352
|
+
sql: joi_1.default.func().required(),
|
|
353
|
+
title: joi_1.default.string(),
|
|
354
|
+
description: joi_1.default.string(),
|
|
355
|
+
meta: joi_1.default.any(),
|
|
356
|
+
shown: joi_1.default.boolean().strict(),
|
|
357
|
+
public: joi_1.default.boolean().strict(),
|
|
347
358
|
}));
|
|
348
359
|
/* *****************************
|
|
349
360
|
* ATTENTION:
|
|
@@ -354,80 +365,80 @@ const SegmentsSchema = Joi.object().pattern(identifierRegex, Joi.object().keys({
|
|
|
354
365
|
const baseSchema = {
|
|
355
366
|
name: identifier,
|
|
356
367
|
refreshKey: CubeRefreshKeySchema,
|
|
357
|
-
fileName:
|
|
358
|
-
extends:
|
|
359
|
-
allDefinitions:
|
|
360
|
-
title:
|
|
361
|
-
sqlAlias:
|
|
362
|
-
dataSource:
|
|
363
|
-
description:
|
|
364
|
-
rewriteQueries:
|
|
365
|
-
shown:
|
|
366
|
-
public:
|
|
367
|
-
joins:
|
|
368
|
-
sql:
|
|
369
|
-
relationship:
|
|
368
|
+
fileName: joi_1.default.string().required(),
|
|
369
|
+
extends: joi_1.default.func(),
|
|
370
|
+
allDefinitions: joi_1.default.func(),
|
|
371
|
+
title: joi_1.default.string(),
|
|
372
|
+
sqlAlias: joi_1.default.string(),
|
|
373
|
+
dataSource: joi_1.default.string(),
|
|
374
|
+
description: joi_1.default.string(),
|
|
375
|
+
rewriteQueries: joi_1.default.boolean().strict(),
|
|
376
|
+
shown: joi_1.default.boolean().strict(),
|
|
377
|
+
public: joi_1.default.boolean().strict(),
|
|
378
|
+
joins: joi_1.default.object().pattern(identifierRegex, joi_1.default.object().keys({
|
|
379
|
+
sql: joi_1.default.func().required(),
|
|
380
|
+
relationship: joi_1.default.any().valid('belongsTo', 'belongs_to', 'many_to_one', 'manyToOne', 'hasMany', 'has_many', 'one_to_many', 'oneToMany', 'hasOne', 'has_one', 'one_to_one', 'oneToOne').required()
|
|
370
381
|
})),
|
|
371
382
|
measures: MeasuresSchema,
|
|
372
|
-
dimensions:
|
|
373
|
-
case:
|
|
374
|
-
when:
|
|
375
|
-
sql:
|
|
376
|
-
label:
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
sql:
|
|
383
|
+
dimensions: joi_1.default.object().pattern(identifierRegex, joi_1.default.alternatives().try(inherit(BaseDimensionWithoutSubQuery, {
|
|
384
|
+
case: joi_1.default.object().keys({
|
|
385
|
+
when: joi_1.default.array().items(joi_1.default.object().keys({
|
|
386
|
+
sql: joi_1.default.func().required(),
|
|
387
|
+
label: joi_1.default.alternatives([
|
|
388
|
+
joi_1.default.string(),
|
|
389
|
+
joi_1.default.object().keys({
|
|
390
|
+
sql: joi_1.default.func().required()
|
|
380
391
|
})
|
|
381
392
|
])
|
|
382
393
|
})),
|
|
383
|
-
else:
|
|
384
|
-
label:
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
sql:
|
|
394
|
+
else: joi_1.default.object().keys({
|
|
395
|
+
label: joi_1.default.alternatives([
|
|
396
|
+
joi_1.default.string(),
|
|
397
|
+
joi_1.default.object().keys({
|
|
398
|
+
sql: joi_1.default.func().required()
|
|
388
399
|
})
|
|
389
400
|
])
|
|
390
401
|
})
|
|
391
402
|
}).required()
|
|
392
403
|
}), inherit(BaseDimensionWithoutSubQuery, {
|
|
393
|
-
latitude:
|
|
394
|
-
sql:
|
|
404
|
+
latitude: joi_1.default.object().keys({
|
|
405
|
+
sql: joi_1.default.func().required()
|
|
395
406
|
}).required(),
|
|
396
|
-
longitude:
|
|
397
|
-
sql:
|
|
407
|
+
longitude: joi_1.default.object().keys({
|
|
408
|
+
sql: joi_1.default.func().required()
|
|
398
409
|
}).required()
|
|
399
410
|
}), inherit(BaseDimension, {
|
|
400
|
-
sql:
|
|
411
|
+
sql: joi_1.default.func().required()
|
|
401
412
|
}))),
|
|
402
413
|
segments: SegmentsSchema,
|
|
403
414
|
preAggregations: PreAggregationsAlternatives,
|
|
404
415
|
};
|
|
405
416
|
const cubeSchema = inherit(baseSchema, {
|
|
406
|
-
sql:
|
|
407
|
-
sqlTable:
|
|
417
|
+
sql: joi_1.default.func(),
|
|
418
|
+
sqlTable: joi_1.default.func(),
|
|
408
419
|
}).xor('sql', 'sqlTable').messages({
|
|
409
420
|
'object.xor': 'You must use either sql or sqlTable within a model, but not both'
|
|
410
421
|
});
|
|
411
422
|
const viewSchema = inherit(baseSchema, {
|
|
412
|
-
isView:
|
|
413
|
-
includes:
|
|
414
|
-
excludes:
|
|
415
|
-
cubes:
|
|
416
|
-
joinPath:
|
|
417
|
-
prefix:
|
|
418
|
-
split:
|
|
419
|
-
alias:
|
|
420
|
-
includes:
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
name:
|
|
426
|
-
alias:
|
|
423
|
+
isView: joi_1.default.boolean().strict(),
|
|
424
|
+
includes: joi_1.default.func(),
|
|
425
|
+
excludes: joi_1.default.func(),
|
|
426
|
+
cubes: joi_1.default.array().items(joi_1.default.object().keys({
|
|
427
|
+
joinPath: joi_1.default.func().required(),
|
|
428
|
+
prefix: joi_1.default.boolean(),
|
|
429
|
+
split: joi_1.default.boolean(),
|
|
430
|
+
alias: joi_1.default.string(),
|
|
431
|
+
includes: joi_1.default.alternatives([
|
|
432
|
+
joi_1.default.string().valid('*'),
|
|
433
|
+
joi_1.default.array().items(joi_1.default.alternatives([
|
|
434
|
+
joi_1.default.string().required(),
|
|
435
|
+
joi_1.default.object().keys({
|
|
436
|
+
name: joi_1.default.string().required(),
|
|
437
|
+
alias: joi_1.default.string()
|
|
427
438
|
})
|
|
428
439
|
]))
|
|
429
440
|
]).required(),
|
|
430
|
-
excludes:
|
|
441
|
+
excludes: joi_1.default.array().items(joi_1.default.string().required()),
|
|
431
442
|
}).oxor('split', 'prefix').messages({
|
|
432
443
|
'object.oxor': 'Using split together with prefix is not supported'
|
|
433
444
|
})),
|
|
@@ -487,7 +498,7 @@ exports.functionFieldsPatterns = functionFieldsPatterns;
|
|
|
487
498
|
class CubeValidator {
|
|
488
499
|
constructor(cubeSymbols) {
|
|
489
500
|
this.cubeSymbols = cubeSymbols;
|
|
490
|
-
this.validCubes =
|
|
501
|
+
this.validCubes = new Map();
|
|
491
502
|
}
|
|
492
503
|
compile(cubes, errorReporter) {
|
|
493
504
|
return this.cubeSymbols.cubeList.map((v) => this.validate(this.cubeSymbols.getCubeDefinition(v.name), errorReporter.inContext(`${v.name} cube`)));
|