@cubejs-backend/schema-compiler 0.23.8 → 0.24.1
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/CHANGELOG.md +54 -0
- package/adapter/AWSElasticSearchQuery.js +2 -2
- package/adapter/BaseFilter.js +65 -18
- package/adapter/BaseQuery.js +10 -23
- package/adapter/BigqueryQuery.js +8 -2
- package/adapter/ClickHouseQuery.js +2 -2
- package/adapter/ElasticSearchQuery.js +2 -2
- package/adapter/HiveQuery.js +2 -2
- package/adapter/MssqlQuery.js +2 -2
- package/adapter/MysqlQuery.js +2 -2
- package/adapter/OracleQuery.js +2 -2
- package/adapter/ParamAllocator.js +2 -1
- package/adapter/PrestodbQuery.js +8 -2
- package/adapter/QueryBuilder.js +1 -0
- package/adapter/SnowflakeQuery.js +6 -0
- package/adapter/SqliteQuery.js +2 -2
- package/compiler/CubeEvaluator.js +2 -2
- package/package.json +3 -3
- package/test/integration/postgres/PreAggregationsTest.js +57 -1
- package/test/integration/postgres/SQLGenerationTest.js +32 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,60 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [0.24.1](https://github.com/cube-js/cube.js/compare/v0.24.0...v0.24.1) (2020-11-27)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* Specifying `dateRange` in time dimension should produce same result as `inDateRange` in filter ([a7603d7](https://github.com/cube-js/cube.js/commit/a7603d724732a51301227f68c39ba699333c0e06)), closes [#962](https://github.com/cube-js/cube.js/issues/962)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [0.24.0](https://github.com/cube-js/cube.js/compare/v0.23.15...v0.24.0) (2020-11-26)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* Error: Type must be provided for null values. -- `null` parameter values are passed to BigQuery when used for dimensions that contain `?` ([6417e7d](https://github.com/cube-js/cube.js/commit/6417e7d120a95c4792557a4c4a0d6abb7c483db9))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* Make default refreshKey to be `every 10 seconds` and enable scheduled refresh in dev mode by default ([221003a](https://github.com/cube-js/cube.js/commit/221003aa73aa1ece3d649de9164a7379a4a690be))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### BREAKING CHANGES
|
|
31
|
+
|
|
32
|
+
* `every 10 seconds` refreshKey becomes a default refreshKey for all cubes.
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## [0.23.15](https://github.com/cube-js/cube.js/compare/v0.23.14...v0.23.15) (2020-11-25)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
### Bug Fixes
|
|
42
|
+
|
|
43
|
+
* Error: Cannot find module 'antlr4/index' ([0d2e330](https://github.com/cube-js/cube.js/commit/0d2e33040dfea3fb80df2a1af2ccff46db0f8673))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
## [0.23.11](https://github.com/cube-js/cube.js/compare/v0.23.10...v0.23.11) (2020-11-13)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
### Features
|
|
53
|
+
|
|
54
|
+
* **@cubejs-backend/mysql-aurora-serverless-driver:** Add a new driver to support AWS Aurora Serverless MySql ([#1333](https://github.com/cube-js/cube.js/issues/1333)) Thanks to [@kcwinner](https://github.com/kcwinner)! ([154fab1](https://github.com/cube-js/cube.js/commit/154fab1a222685e1e83d5187a4f00f745c4613a3))
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
6
60
|
## [0.23.8](https://github.com/cube-js/cube.js/compare/v0.23.7...v0.23.8) (2020-11-06)
|
|
7
61
|
|
|
8
62
|
**Note:** Version bump only for package @cubejs-backend/schema-compiler
|
|
@@ -16,8 +16,8 @@ const GRANULARITY_TO_INTERVAL = {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
class AWSElasticSearchQueryFilter extends BaseFilter {
|
|
19
|
-
likeIgnoreCase(column, not) {
|
|
20
|
-
return `${column}${not ? ' NOT' : ''} LIKE CONCAT('%',
|
|
19
|
+
likeIgnoreCase(column, not, param) {
|
|
20
|
+
return `${column}${not ? ' NOT' : ''} LIKE CONCAT('%', ${this.allocateParam(param)}, '%')`;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
package/adapter/BaseFilter.js
CHANGED
|
@@ -48,8 +48,16 @@ class BaseFilter extends BaseDimension {
|
|
|
48
48
|
/[A-Z]/,
|
|
49
49
|
(c) => (c != null ? c : '').toLowerCase()
|
|
50
50
|
)}Where`;
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
|
|
52
|
+
let sql = this[operatorMethod](columnSql);
|
|
53
|
+
if (sql.match(this.query.paramAllocator.paramsMatchRegex)) {
|
|
54
|
+
return sql;
|
|
55
|
+
}
|
|
56
|
+
// TODO DEPRECATED: remove and replace with error
|
|
57
|
+
// columnSql can contain `?` so allocate params first and then substitute columnSql
|
|
58
|
+
// fallback implementation for drivers that still use `?` substitution
|
|
59
|
+
sql = this[operatorMethod]('$$$COLUMN$$$');
|
|
60
|
+
return this.query.paramAllocator.allocateParamsForQuestionString(sql, this.filterParams()).replace(/\$\$\$COLUMN\$\$\$/g, columnSql);
|
|
53
61
|
}
|
|
54
62
|
|
|
55
63
|
measureDefinition() {
|
|
@@ -107,6 +115,37 @@ class BaseFilter extends BaseDimension {
|
|
|
107
115
|
return '?';
|
|
108
116
|
}
|
|
109
117
|
|
|
118
|
+
firstParameter() {
|
|
119
|
+
const params = this.filterParams();
|
|
120
|
+
if (!params[0]) {
|
|
121
|
+
throw new Error('Expected one parameter but nothing found');
|
|
122
|
+
}
|
|
123
|
+
return this.allocateCastParam(params[0]);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
allocateCastParam(param) {
|
|
127
|
+
return this.query.paramAllocator.allocateParamsForQuestionString(this.castParameter(), [param]);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
allocateTimestampParam(param) {
|
|
131
|
+
return this.query.paramAllocator.allocateParamsForQuestionString(this.query.timeStampParam(this), [param]);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
allocateTimestampParams() {
|
|
135
|
+
return this.filterParams().map((p, i) => {
|
|
136
|
+
if (i > 1) {
|
|
137
|
+
throw new Error(`Expected only 2 parameters for timestamp filter but got: ${this.filterParams()}`);
|
|
138
|
+
}
|
|
139
|
+
return this.allocateTimestampParam(
|
|
140
|
+
i === 0 ? this.inDbTimeZoneDateFrom(p) : this.inDbTimeZoneDateTo(p)
|
|
141
|
+
);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
allParamsRepeat(basePart) {
|
|
146
|
+
return this.filterParams().map(p => this.query.paramAllocator.allocateParamsForQuestionString(basePart, [p]));
|
|
147
|
+
}
|
|
148
|
+
|
|
110
149
|
isArrayValues() {
|
|
111
150
|
return Array.isArray(this.values) && this.values.length > 1;
|
|
112
151
|
}
|
|
@@ -120,8 +159,7 @@ class BaseFilter extends BaseDimension {
|
|
|
120
159
|
}
|
|
121
160
|
|
|
122
161
|
likeOr(column, not) {
|
|
123
|
-
|
|
124
|
-
return `${join(not ? ' AND ' : ' OR ', repeat(basePart, this.filterParams().length))}${this.orIsNullCheck(column, not)}`;
|
|
162
|
+
return `${join(not ? ' AND ' : ' OR ', this.filterParams().map(p => this.likeIgnoreCase(column, not, p)))}${this.orIsNullCheck(column, not)}`;
|
|
125
163
|
}
|
|
126
164
|
|
|
127
165
|
orIsNullCheck(column, not) {
|
|
@@ -132,8 +170,12 @@ class BaseFilter extends BaseDimension {
|
|
|
132
170
|
return not ? !this.valuesContainNull() : this.valuesContainNull();
|
|
133
171
|
}
|
|
134
172
|
|
|
135
|
-
likeIgnoreCase(column, not) {
|
|
136
|
-
return `${column}${not ? ' NOT' : ''} ILIKE '%' ||
|
|
173
|
+
likeIgnoreCase(column, not, param) {
|
|
174
|
+
return `${column}${not ? ' NOT' : ''} ILIKE '%' || ${this.allocateParam(param)} || '%'`;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
allocateParam(param) {
|
|
178
|
+
return this.query.paramAllocator.allocateParam(param);
|
|
137
179
|
}
|
|
138
180
|
|
|
139
181
|
equalsWhere(column) {
|
|
@@ -145,11 +187,11 @@ class BaseFilter extends BaseDimension {
|
|
|
145
187
|
return this.notSetWhere(column);
|
|
146
188
|
}
|
|
147
189
|
|
|
148
|
-
return `${column} = ${this.
|
|
190
|
+
return `${column} = ${this.firstParameter()}${this.orIsNullCheck(column, false)}`;
|
|
149
191
|
}
|
|
150
192
|
|
|
151
193
|
inPlaceholders() {
|
|
152
|
-
return `(${join(', ',
|
|
194
|
+
return `(${join(', ', this.filterParams().map(p => this.allocateCastParam(p)))})`;
|
|
153
195
|
}
|
|
154
196
|
|
|
155
197
|
inWhere(column) {
|
|
@@ -165,7 +207,7 @@ class BaseFilter extends BaseDimension {
|
|
|
165
207
|
return this.setWhere(column);
|
|
166
208
|
}
|
|
167
209
|
|
|
168
|
-
return `${column} <> ${this.
|
|
210
|
+
return `${column} <> ${this.firstParameter()}${this.orIsNullCheck(column, true)}`;
|
|
169
211
|
}
|
|
170
212
|
|
|
171
213
|
notInWhere(column) {
|
|
@@ -181,19 +223,19 @@ class BaseFilter extends BaseDimension {
|
|
|
181
223
|
}
|
|
182
224
|
|
|
183
225
|
gtWhere(column) {
|
|
184
|
-
return `${column} > ${this.
|
|
226
|
+
return `${column} > ${this.firstParameter()}`;
|
|
185
227
|
}
|
|
186
228
|
|
|
187
229
|
gteWhere(column) {
|
|
188
|
-
return `${column} >= ${this.
|
|
230
|
+
return `${column} >= ${this.firstParameter()}`;
|
|
189
231
|
}
|
|
190
232
|
|
|
191
233
|
ltWhere(column) {
|
|
192
|
-
return `${column} < ${this.
|
|
234
|
+
return `${column} < ${this.firstParameter()}`;
|
|
193
235
|
}
|
|
194
236
|
|
|
195
237
|
lteWhere(column) {
|
|
196
|
-
return `${column} <= ${this.
|
|
238
|
+
return `${column} <= ${this.firstParameter()}`;
|
|
197
239
|
}
|
|
198
240
|
|
|
199
241
|
expressionEqualsWhere(column) {
|
|
@@ -201,23 +243,28 @@ class BaseFilter extends BaseDimension {
|
|
|
201
243
|
}
|
|
202
244
|
|
|
203
245
|
inDateRangeWhere(column) {
|
|
204
|
-
|
|
246
|
+
const [from, to] = this.allocateTimestampParams();
|
|
247
|
+
return this.query.timeRangeFilter(column, from, to);
|
|
205
248
|
}
|
|
206
249
|
|
|
207
250
|
notInDateRangeWhere(column) {
|
|
208
|
-
|
|
251
|
+
const [from, to] = this.allocateTimestampParams();
|
|
252
|
+
return this.query.timeNotInRangeFilter(column, from, to);
|
|
209
253
|
}
|
|
210
254
|
|
|
211
255
|
onTheDateWhere(column) {
|
|
212
|
-
|
|
256
|
+
const [from, to] = this.allocateTimestampParams();
|
|
257
|
+
return this.query.timeRangeFilter(column, from, to);
|
|
213
258
|
}
|
|
214
259
|
|
|
215
260
|
beforeDateWhere(column) {
|
|
216
|
-
|
|
261
|
+
const [before] = this.allocateTimestampParams();
|
|
262
|
+
return this.query.beforeDateFilter(column, before);
|
|
217
263
|
}
|
|
218
264
|
|
|
219
265
|
afterDateWhere(column) {
|
|
220
|
-
|
|
266
|
+
const [after] = this.allocateTimestampParams();
|
|
267
|
+
return this.query.afterDateFilter(column, after);
|
|
221
268
|
}
|
|
222
269
|
|
|
223
270
|
formatFromDate(date) {
|
package/adapter/BaseQuery.js
CHANGED
|
@@ -1666,25 +1666,7 @@ class BaseQuery {
|
|
|
1666
1666
|
}
|
|
1667
1667
|
}
|
|
1668
1668
|
refreshKeyAllSetManually = false;
|
|
1669
|
-
|
|
1670
|
-
!(cubeFromPath.refreshKey && cubeFromPath.refreshKey.immutable) ?
|
|
1671
|
-
this.cubeEvaluator.timeDimensionPathsForCube(cube) :
|
|
1672
|
-
[];
|
|
1673
|
-
if (timeDimensions.length) {
|
|
1674
|
-
const dimension = timeDimensions.filter(f => f.toLowerCase().indexOf('update') !== -1)[0] || timeDimensions[0];
|
|
1675
|
-
const foundMainTimeDimension = this.newTimeDimension({ dimension });
|
|
1676
|
-
const aggSelect = this.evaluateSymbolSqlWithContext(
|
|
1677
|
-
() => this.aggSelectForDimension(cube, foundMainTimeDimension, 'max'),
|
|
1678
|
-
{ preAggregationQuery: true }
|
|
1679
|
-
);
|
|
1680
|
-
if (aggSelect) {
|
|
1681
|
-
return aggSelect;
|
|
1682
|
-
}
|
|
1683
|
-
}
|
|
1684
|
-
return this.evaluateSymbolSqlWithContext(
|
|
1685
|
-
() => `select count(*) from ${this.cubeSql(cube)} ${this.asSyntaxTable} ${this.cubeAlias(cube)}`,
|
|
1686
|
-
{ preAggregationQuery: true }
|
|
1687
|
-
);
|
|
1669
|
+
return `SELECT ${this.everyRefreshKeySql(this.defaultEveryRefreshKey())}`;
|
|
1688
1670
|
};
|
|
1689
1671
|
const queries = cubes
|
|
1690
1672
|
.map(cube => [cube, refreshKeyQueryByCube(cube)])
|
|
@@ -1967,6 +1949,12 @@ class BaseQuery {
|
|
|
1967
1949
|
return 10;
|
|
1968
1950
|
}
|
|
1969
1951
|
|
|
1952
|
+
defaultEveryRefreshKey() {
|
|
1953
|
+
return {
|
|
1954
|
+
every: '10 seconds'
|
|
1955
|
+
};
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1970
1958
|
preAggregationInvalidateKeyQueries(cube, preAggregation) {
|
|
1971
1959
|
return this.cacheValue(
|
|
1972
1960
|
['preAggregationInvalidateKeyQueries', cube, JSON.stringify(preAggregation)],
|
|
@@ -2027,10 +2015,9 @@ class BaseQuery {
|
|
|
2027
2015
|
if (cubeFromPath.refreshKey && cubeFromPath.refreshKey.immutable) {
|
|
2028
2016
|
return `SELECT ${this.incrementalRefreshKey(preAggregationQueryForSql, `(${originalRefreshKey})`)}`;
|
|
2029
2017
|
} else if (!cubeFromPath.refreshKey) {
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
originalRefreshKey;
|
|
2018
|
+
return `SELECT ${this.everyRefreshKeySql({
|
|
2019
|
+
every: '1 hour'
|
|
2020
|
+
})}`;
|
|
2034
2021
|
}
|
|
2035
2022
|
return originalRefreshKey;
|
|
2036
2023
|
}
|
package/adapter/BigqueryQuery.js
CHANGED
|
@@ -12,8 +12,8 @@ const GRANULARITY_TO_INTERVAL = {
|
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
class BigqueryFilter extends BaseFilter {
|
|
15
|
-
likeIgnoreCase(column, not) {
|
|
16
|
-
return `LOWER(${column})${not ? ' NOT' : ''} LIKE CONCAT('%', LOWER(
|
|
15
|
+
likeIgnoreCase(column, not, param) {
|
|
16
|
+
return `LOWER(${column})${not ? ' NOT' : ''} LIKE CONCAT('%', LOWER(${this.allocateParam(param)}) ,'%')`;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
castParameter() {
|
|
@@ -133,6 +133,12 @@ class BigqueryQuery extends BaseQuery {
|
|
|
133
133
|
defaultRefreshKeyRenewalThreshold() {
|
|
134
134
|
return 120;
|
|
135
135
|
}
|
|
136
|
+
|
|
137
|
+
defaultEveryRefreshKey() {
|
|
138
|
+
return {
|
|
139
|
+
every: '2 minutes'
|
|
140
|
+
};
|
|
141
|
+
}
|
|
136
142
|
}
|
|
137
143
|
|
|
138
144
|
module.exports = BigqueryQuery;
|
|
@@ -13,8 +13,8 @@ const GRANULARITY_TO_INTERVAL = {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
class ClickHouseFilter extends BaseFilter {
|
|
16
|
-
likeIgnoreCase(column, not) {
|
|
17
|
-
return `lower(${column}) ${not ? 'NOT' : ''} LIKE CONCAT('%', lower(
|
|
16
|
+
likeIgnoreCase(column, not, param) {
|
|
17
|
+
return `lower(${column}) ${not ? 'NOT' : ''} LIKE CONCAT('%', lower(${this.allocateParam(param)}), '%')`;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
castParameter() {
|
|
@@ -16,8 +16,8 @@ const GRANULARITY_TO_INTERVAL = {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
class ElasticSearchQueryFilter extends BaseFilter {
|
|
19
|
-
likeIgnoreCase(column, not) {
|
|
20
|
-
return `${not ? " NOT" : ""} MATCH(${column},
|
|
19
|
+
likeIgnoreCase(column, not, param) {
|
|
20
|
+
return `${not ? " NOT" : ""} MATCH(${column}, ${this.allocateParam(param)}, 'fuzziness=AUTO:1,5')`;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
package/adapter/HiveQuery.js
CHANGED
|
@@ -14,8 +14,8 @@ const GRANULARITY_TO_INTERVAL = {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
class HiveFilter extends BaseFilter {
|
|
17
|
-
likeIgnoreCase(column, not) {
|
|
18
|
-
return `${column}${not ? ' NOT' : ''} LIKE CONCAT('%',
|
|
17
|
+
likeIgnoreCase(column, not, param) {
|
|
18
|
+
return `${column}${not ? ' NOT' : ''} LIKE CONCAT('%', ${this.allocateParam(param)}, '%')`;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
package/adapter/MssqlQuery.js
CHANGED
|
@@ -43,8 +43,8 @@ class MssqlFilter extends BaseFilter {
|
|
|
43
43
|
return typeof param === 'string' ? param.replace(/([_%])/gi, '[$1]') : param;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
likeIgnoreCase(column, not) {
|
|
47
|
-
return `LOWER(${column})${not ? ' NOT' : ''} LIKE CONCAT('%', LOWER(
|
|
46
|
+
likeIgnoreCase(column, not, param) {
|
|
47
|
+
return `LOWER(${column})${not ? ' NOT' : ''} LIKE CONCAT('%', LOWER(${this.allocateParam(param)}) ,'%')`;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
package/adapter/MysqlQuery.js
CHANGED
|
@@ -15,8 +15,8 @@ const GRANULARITY_TO_INTERVAL = {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
class MysqlFilter extends BaseFilter {
|
|
18
|
-
likeIgnoreCase(column, not) {
|
|
19
|
-
return `${column}${not ? ' NOT' : ''} LIKE CONCAT('%',
|
|
18
|
+
likeIgnoreCase(column, not, param) {
|
|
19
|
+
return `${column}${not ? ' NOT' : ''} LIKE CONCAT('%', ${this.allocateParam(param)}, '%')`;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
package/adapter/OracleQuery.js
CHANGED
|
@@ -20,8 +20,8 @@ class OracleFilter extends BaseFilter {
|
|
|
20
20
|
/**
|
|
21
21
|
* "ILIKE" does't support
|
|
22
22
|
*/
|
|
23
|
-
likeIgnoreCase(column, not) {
|
|
24
|
-
return `${column}${not ? ' NOT' : ''} LIKE '%' || ${this.
|
|
23
|
+
likeIgnoreCase(column, not, param) {
|
|
24
|
+
return `${column}${not ? ' NOT' : ''} LIKE '%' || ${this.allocateParam(param)} || '%'`;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
class ParamAllocator {
|
|
2
2
|
constructor() {
|
|
3
3
|
this.params = [];
|
|
4
|
+
this.paramsMatchRegex = /\$(\d+)\$/g;
|
|
4
5
|
}
|
|
5
6
|
|
|
6
7
|
allocateParam(param) {
|
|
@@ -16,7 +17,7 @@ class ParamAllocator {
|
|
|
16
17
|
|
|
17
18
|
buildSqlAndParams(annotatedSql) {
|
|
18
19
|
const paramsInSqlOrder = [];
|
|
19
|
-
return [annotatedSql.replace(
|
|
20
|
+
return [annotatedSql.replace(this.paramsMatchRegex, (match, paramIndex) => {
|
|
20
21
|
paramsInSqlOrder.push(this.params[paramIndex]);
|
|
21
22
|
return this.paramPlaceHolder(paramsInSqlOrder.length - 1);
|
|
22
23
|
}), paramsInSqlOrder];
|
package/adapter/PrestodbQuery.js
CHANGED
|
@@ -12,8 +12,8 @@ const GRANULARITY_TO_INTERVAL = {
|
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
class PrestodbFilter extends BaseFilter {
|
|
15
|
-
likeIgnoreCase(column, not) {
|
|
16
|
-
return `LOWER(${column})${not ? ' NOT' : ''} LIKE CONCAT('%', LOWER(
|
|
15
|
+
likeIgnoreCase(column, not, param) {
|
|
16
|
+
return `LOWER(${column})${not ? ' NOT' : ''} LIKE CONCAT('%', LOWER(${this.allocateParam(param)}) ,'%') ESCAPE '\\'`;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
castParameter() {
|
|
@@ -81,6 +81,12 @@ class PrestodbQuery extends BaseQuery {
|
|
|
81
81
|
return 120;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
defaultEveryRefreshKey() {
|
|
85
|
+
return {
|
|
86
|
+
every: '2 minutes'
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
84
90
|
hllInit(sql) {
|
|
85
91
|
return `cast(approx_set(${sql}) as varbinary)`;
|
|
86
92
|
}
|
package/adapter/QueryBuilder.js
CHANGED
package/adapter/SqliteQuery.js
CHANGED
|
@@ -14,8 +14,8 @@ const GRANULARITY_TO_INTERVAL = {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
class SqliteFilter extends BaseFilter {
|
|
17
|
-
likeIgnoreCase(column, not) {
|
|
18
|
-
return `${column}${not ? ' NOT' : ''} LIKE '%' ||
|
|
17
|
+
likeIgnoreCase(column, not, param) {
|
|
18
|
+
return `${column}${not ? ' NOT' : ''} LIKE '%' || ${this.allocateParam(param)} || '%' COLLATE NOCASE`;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
@@ -60,8 +60,8 @@ class CubeEvaluator extends CubeSymbols {
|
|
|
60
60
|
}).reduce((a, b) => a.concat(b), []);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
return Object.keys(this.evaluatedCubes)
|
|
63
|
+
cubeNames() {
|
|
64
|
+
return Object.keys(this.evaluatedCubes);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
isMeasure(measurePath) {
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@cubejs-backend/schema-compiler",
|
|
3
3
|
"description": "Cube.js schema compiler",
|
|
4
4
|
"author": "Cube Dev, Inc.",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.24.1",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/cube-js/cube.js.git",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@babel/traverse": "^7.4.0",
|
|
31
31
|
"@babel/types": "^7.4.0",
|
|
32
32
|
"@hapi/joi": "^15.1.1",
|
|
33
|
-
"antlr4": "
|
|
33
|
+
"antlr4": "4.8.0",
|
|
34
34
|
"cron-parser": "^2.16.3",
|
|
35
35
|
"humps": "^2.0.1",
|
|
36
36
|
"inflection": "^1.12.0",
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"uuid": "^3.3.2"
|
|
63
63
|
},
|
|
64
64
|
"license": "Apache-2.0",
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "0479050307f08ca69f4fdaee2d08d3e4f39453e6"
|
|
66
66
|
}
|
|
@@ -138,6 +138,14 @@ describe('PreAggregations', function test() {
|
|
|
138
138
|
granularity: 'hour',
|
|
139
139
|
partitionGranularity: 'hour'
|
|
140
140
|
},
|
|
141
|
+
partitionedHourlyForRange: {
|
|
142
|
+
type: 'rollup',
|
|
143
|
+
measureReferences: [checkinsTotal],
|
|
144
|
+
dimensionReferences: [source, createdAt],
|
|
145
|
+
timeDimensionReference: createdAt,
|
|
146
|
+
granularity: 'hour',
|
|
147
|
+
partitionGranularity: 'hour'
|
|
148
|
+
},
|
|
141
149
|
ratio: {
|
|
142
150
|
type: 'rollup',
|
|
143
151
|
measureReferences: [checkinsTotal, uniqueSourceCount],
|
|
@@ -599,7 +607,7 @@ describe('PreAggregations', function test() {
|
|
|
599
607
|
const preAggregationsDescription = query.preAggregations.preAggregationsDescription();
|
|
600
608
|
console.log(JSON.stringify(preAggregationsDescription, null, 2));
|
|
601
609
|
|
|
602
|
-
preAggregationsDescription[0].invalidateKeyQueries[0][0].should.match(
|
|
610
|
+
preAggregationsDescription[0].invalidateKeyQueries[0][0].should.match(/FLOOR/);
|
|
603
611
|
|
|
604
612
|
return dbRunner.testQueries(tempTablePreAggregations(preAggregationsDescription).concat([
|
|
605
613
|
query.buildSqlAndParams()
|
|
@@ -795,6 +803,54 @@ describe('PreAggregations', function test() {
|
|
|
795
803
|
});
|
|
796
804
|
}));
|
|
797
805
|
|
|
806
|
+
it('partitioned inDateRange', () => compiler.compile().then(() => {
|
|
807
|
+
const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, {
|
|
808
|
+
measures: [
|
|
809
|
+
'visitors.checkinsTotal'
|
|
810
|
+
],
|
|
811
|
+
dimensions: [
|
|
812
|
+
'visitors.source'
|
|
813
|
+
],
|
|
814
|
+
timezone: 'America/Los_Angeles',
|
|
815
|
+
preAggregationsSchema: '',
|
|
816
|
+
filters: [{
|
|
817
|
+
member: 'visitors.createdAt',
|
|
818
|
+
operator: 'inDateRange',
|
|
819
|
+
values: ['2016-12-30', '2017-01-05']
|
|
820
|
+
}],
|
|
821
|
+
order: [{
|
|
822
|
+
id: 'visitors.checkinsTotal'
|
|
823
|
+
}],
|
|
824
|
+
});
|
|
825
|
+
|
|
826
|
+
const queryAndParams = query.buildSqlAndParams();
|
|
827
|
+
console.log(queryAndParams);
|
|
828
|
+
const preAggregationsDescription = query.preAggregations.preAggregationsDescription();
|
|
829
|
+
console.log(JSON.stringify(preAggregationsDescription, null, 2));
|
|
830
|
+
|
|
831
|
+
const queries = tempTablePreAggregations(preAggregationsDescription);
|
|
832
|
+
|
|
833
|
+
console.log(JSON.stringify(queries.concat(queryAndParams)));
|
|
834
|
+
|
|
835
|
+
return dbRunner.testQueries(
|
|
836
|
+
queries.concat([queryAndParams]).map(q => replaceTableName(q, preAggregationsDescription, 12342))
|
|
837
|
+
).then(res => {
|
|
838
|
+
console.log(JSON.stringify(res));
|
|
839
|
+
res.should.be.deepEqual(
|
|
840
|
+
[
|
|
841
|
+
{
|
|
842
|
+
'visitors__source': 'google',
|
|
843
|
+
'visitors__checkins_total': '1'
|
|
844
|
+
},
|
|
845
|
+
{
|
|
846
|
+
'visitors__source': 'some',
|
|
847
|
+
'visitors__checkins_total': '5'
|
|
848
|
+
}
|
|
849
|
+
]
|
|
850
|
+
);
|
|
851
|
+
});
|
|
852
|
+
}));
|
|
853
|
+
|
|
798
854
|
it('partitioned hourly', () => compiler.compile().then(() => {
|
|
799
855
|
const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, {
|
|
800
856
|
measures: [
|
|
@@ -164,6 +164,10 @@ describe('SQL Generation', function test() {
|
|
|
164
164
|
type: \`geo\`,
|
|
165
165
|
latitude: { sql: \`latitude\` },
|
|
166
166
|
longitude: { sql: \`longitude\` }
|
|
167
|
+
},
|
|
168
|
+
questionMark: {
|
|
169
|
+
sql: \`replace('some string question string???', 'string', 'with some ???')\`,
|
|
170
|
+
type: \`string\`
|
|
167
171
|
}
|
|
168
172
|
}
|
|
169
173
|
})
|
|
@@ -1646,6 +1650,34 @@ describe('SQL Generation', function test() {
|
|
|
1646
1650
|
])
|
|
1647
1651
|
);
|
|
1648
1652
|
|
|
1653
|
+
it(
|
|
1654
|
+
'question mark filter',
|
|
1655
|
+
() => runQueryTest({
|
|
1656
|
+
measures: ['visitors.visitor_count'],
|
|
1657
|
+
dimensions: [],
|
|
1658
|
+
timeDimensions: [],
|
|
1659
|
+
timezone: 'America/Los_Angeles',
|
|
1660
|
+
filters: [{
|
|
1661
|
+
or: [{
|
|
1662
|
+
member: 'visitors.questionMark',
|
|
1663
|
+
operator: 'contains',
|
|
1664
|
+
values: ['with some']
|
|
1665
|
+
}, {
|
|
1666
|
+
member: 'visitors.questionMark',
|
|
1667
|
+
operator: 'equals',
|
|
1668
|
+
values: [null]
|
|
1669
|
+
}, {
|
|
1670
|
+
member: 'visitors.questionMark',
|
|
1671
|
+
operator: 'equals',
|
|
1672
|
+
values: [null, 'with some']
|
|
1673
|
+
}]
|
|
1674
|
+
}],
|
|
1675
|
+
order: []
|
|
1676
|
+
}, [
|
|
1677
|
+
{ 'visitors__visitor_count': '6' }
|
|
1678
|
+
])
|
|
1679
|
+
);
|
|
1680
|
+
|
|
1649
1681
|
const baseQuery = {
|
|
1650
1682
|
measures: [
|
|
1651
1683
|
'visitors.countDistinctApproxRolling'
|