@cubejs-backend/schema-compiler 1.3.23 → 1.3.24
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 +3 -9
- package/dist/src/adapter/AWSElasticSearchQuery.d.ts.map +1 -1
- package/dist/src/adapter/AWSElasticSearchQuery.js +4 -50
- package/dist/src/adapter/AWSElasticSearchQuery.js.map +1 -1
- package/dist/src/adapter/BaseMeasure.d.ts +1 -1
- package/dist/src/adapter/BaseQuery.d.ts +38 -8
- package/dist/src/adapter/BaseQuery.d.ts.map +1 -1
- package/dist/src/adapter/BaseQuery.js +175 -29
- package/dist/src/adapter/BaseQuery.js.map +1 -1
- package/dist/src/adapter/BigqueryQuery.d.ts +21 -2
- package/dist/src/adapter/BigqueryQuery.d.ts.map +1 -1
- package/dist/src/adapter/BigqueryQuery.js +80 -14
- package/dist/src/adapter/BigqueryQuery.js.map +1 -1
- package/dist/src/adapter/ClickHouseQuery.d.ts +4 -2
- package/dist/src/adapter/ClickHouseQuery.d.ts.map +1 -1
- package/dist/src/adapter/ClickHouseQuery.js +0 -13
- package/dist/src/adapter/ClickHouseQuery.js.map +1 -1
- package/dist/src/adapter/ElasticSearchQuery.d.ts +9 -2
- package/dist/src/adapter/ElasticSearchQuery.d.ts.map +1 -1
- package/dist/src/adapter/ElasticSearchQuery.js +30 -7
- package/dist/src/adapter/ElasticSearchQuery.js.map +1 -1
- package/dist/src/adapter/HiveQuery.d.ts +1 -1
- package/dist/src/adapter/HiveQuery.d.ts.map +1 -1
- package/dist/src/adapter/HiveQuery.js +3 -3
- package/dist/src/adapter/HiveQuery.js.map +1 -1
- package/dist/src/adapter/QueryBuilder.d.ts +2 -2
- package/dist/src/adapter/QueryBuilder.d.ts.map +1 -1
- package/dist/src/adapter/QueryBuilder.js.map +1 -1
- package/dist/src/adapter/QueryCache.d.ts +3 -4
- package/dist/src/adapter/QueryCache.d.ts.map +1 -1
- package/dist/src/adapter/QueryCache.js +1 -2
- package/dist/src/adapter/QueryCache.js.map +1 -1
- package/dist/src/compiler/CubeSymbols.d.ts.map +1 -1
- package/dist/src/compiler/CubeSymbols.js +4 -1
- package/dist/src/compiler/CubeSymbols.js.map +1 -1
- package/dist/src/compiler/DataSchemaCompiler.d.ts +92 -69
- package/dist/src/compiler/DataSchemaCompiler.d.ts.map +1 -1
- package/dist/src/compiler/DataSchemaCompiler.js +63 -41
- package/dist/src/compiler/DataSchemaCompiler.js.map +1 -1
- package/dist/src/compiler/ErrorReporter.d.ts +1 -1
- package/dist/src/compiler/ErrorReporter.d.ts.map +1 -1
- package/dist/src/compiler/PrepareCompiler.d.ts +5 -10
- package/dist/src/compiler/PrepareCompiler.d.ts.map +1 -1
- package/dist/src/compiler/PrepareCompiler.js.map +1 -1
- package/dist/src/compiler/YamlCompiler.d.ts +1 -1
- package/dist/src/compiler/YamlCompiler.d.ts.map +1 -1
- package/dist/src/compiler/YamlCompiler.js.map +1 -1
- package/package.json +6 -6
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare class AWSElasticSearchQuery extends
|
|
1
|
+
import { ElasticSearchQuery } from './ElasticSearchQuery';
|
|
2
|
+
export declare class AWSElasticSearchQuery extends ElasticSearchQuery {
|
|
3
3
|
newFilter(filter: any): any;
|
|
4
|
-
convertTz(field: any): string;
|
|
5
|
-
timeStampCast(value: any): string;
|
|
6
|
-
dateTimeCast(value: any): string;
|
|
7
4
|
subtractInterval(date: any, interval: any): string;
|
|
8
5
|
addInterval(date: any, interval: any): string;
|
|
9
6
|
timeGroupedColumn(granularity: any, dimension: any): any;
|
|
10
|
-
|
|
11
|
-
orderHashToString(hash: any): string | null;
|
|
12
|
-
getFieldAlias(id: any): any;
|
|
13
|
-
escapeColumnName(name: any): string;
|
|
7
|
+
unixTimestampSql(): string;
|
|
14
8
|
}
|
|
15
9
|
//# sourceMappingURL=AWSElasticSearchQuery.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AWSElasticSearchQuery.d.ts","sourceRoot":"","sources":["../../../src/adapter/AWSElasticSearchQuery.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AWSElasticSearchQuery.d.ts","sourceRoot":"","sources":["../../../src/adapter/AWSElasticSearchQuery.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAqB1D,qBAAa,qBAAsB,SAAQ,kBAAkB;IAC3C,SAAS,CAAC,MAAM,KAAA;IAIhB,gBAAgB,CAAC,IAAI,KAAA,EAAE,QAAQ,KAAA;IAI/B,WAAW,CAAC,IAAI,KAAA,EAAE,QAAQ,KAAA;IAI1B,iBAAiB,CAAC,WAAW,KAAA,EAAE,SAAS,KAAA;IAIxC,gBAAgB;CAGjC"}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.AWSElasticSearchQuery = void 0;
|
|
7
|
-
const ramda_1 = __importDefault(require("ramda"));
|
|
8
4
|
const BaseFilter_1 = require("./BaseFilter");
|
|
9
|
-
const
|
|
5
|
+
const ElasticSearchQuery_1 = require("./ElasticSearchQuery");
|
|
10
6
|
const GRANULARITY_TO_INTERVAL = {
|
|
11
7
|
day: (date) => `DATE_FORMAT(${date}, 'yyyy-MM-dd 00:00:00.000')`,
|
|
12
8
|
// eslint-disable-next-line no-unused-vars,@typescript-eslint/no-unused-vars
|
|
@@ -24,19 +20,10 @@ class AWSElasticSearchQueryFilter extends BaseFilter_1.BaseFilter {
|
|
|
24
20
|
return `${column}${not ? ' NOT' : ''} LIKE CONCAT('${p}', ${this.allocateParam(param)}, '${s}')`;
|
|
25
21
|
}
|
|
26
22
|
}
|
|
27
|
-
class AWSElasticSearchQuery extends
|
|
23
|
+
class AWSElasticSearchQuery extends ElasticSearchQuery_1.ElasticSearchQuery {
|
|
28
24
|
newFilter(filter) {
|
|
29
25
|
return new AWSElasticSearchQueryFilter(this, filter);
|
|
30
26
|
}
|
|
31
|
-
convertTz(field) {
|
|
32
|
-
return `${field}`; // TODO
|
|
33
|
-
}
|
|
34
|
-
timeStampCast(value) {
|
|
35
|
-
return `${value}`;
|
|
36
|
-
}
|
|
37
|
-
dateTimeCast(value) {
|
|
38
|
-
return `${value}`; // TODO
|
|
39
|
-
}
|
|
40
27
|
subtractInterval(date, interval) {
|
|
41
28
|
return `DATE_SUB(${date}, INTERVAL ${interval})`;
|
|
42
29
|
}
|
|
@@ -46,41 +33,8 @@ class AWSElasticSearchQuery extends BaseQuery_1.BaseQuery {
|
|
|
46
33
|
timeGroupedColumn(granularity, dimension) {
|
|
47
34
|
return GRANULARITY_TO_INTERVAL[granularity](dimension);
|
|
48
35
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return '';
|
|
52
|
-
}
|
|
53
|
-
const dimensionsForSelect = this.dimensionsForSelect();
|
|
54
|
-
const dimensionColumns = ramda_1.default.flatten(dimensionsForSelect.map(s => s.selectColumns() && s.dimensionSql()))
|
|
55
|
-
.filter(s => !!s);
|
|
56
|
-
return dimensionColumns.length ? ` GROUP BY ${dimensionColumns.join(', ')}` : '';
|
|
57
|
-
}
|
|
58
|
-
orderHashToString(hash) {
|
|
59
|
-
if (!hash || !hash.id) {
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
const fieldAlias = this.getFieldAlias(hash.id);
|
|
63
|
-
if (fieldAlias === null) {
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
const direction = hash.desc ? 'DESC' : 'ASC';
|
|
67
|
-
return `${fieldAlias} ${direction}`;
|
|
68
|
-
}
|
|
69
|
-
getFieldAlias(id) {
|
|
70
|
-
const equalIgnoreCase = (a, b) => (typeof a === 'string' && typeof b === 'string' && a.toUpperCase() === b.toUpperCase());
|
|
71
|
-
let field;
|
|
72
|
-
field = this.dimensionsForSelect().find(d => equalIgnoreCase(d.dimension, id));
|
|
73
|
-
if (field) {
|
|
74
|
-
return field.dimensionSql();
|
|
75
|
-
}
|
|
76
|
-
field = this.measures.find(d => equalIgnoreCase(d.measure, id) || equalIgnoreCase(d.expressionName, id));
|
|
77
|
-
if (field) {
|
|
78
|
-
return field.aliasName(); // TODO isn't supported
|
|
79
|
-
}
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
escapeColumnName(name) {
|
|
83
|
-
return `${name}`; // TODO
|
|
36
|
+
unixTimestampSql() {
|
|
37
|
+
return 'EXTRACT(EPOCH FROM NOW())';
|
|
84
38
|
}
|
|
85
39
|
}
|
|
86
40
|
exports.AWSElasticSearchQuery = AWSElasticSearchQuery;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AWSElasticSearchQuery.js","sourceRoot":"","sources":["../../../src/adapter/AWSElasticSearchQuery.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AWSElasticSearchQuery.js","sourceRoot":"","sources":["../../../src/adapter/AWSElasticSearchQuery.ts"],"names":[],"mappings":";;;AAAA,6CAA0C;AAC1C,6DAA0D;AAE1D,MAAM,uBAAuB,GAAG;IAC9B,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,IAAI,8BAA8B;IAChE,4EAA4E;IAC5E,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC3D,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,IAAI,8BAA8B;IACjE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,IAAI,8BAA8B;IACnE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,IAAI,8BAA8B;IACnE,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,IAAI,8BAA8B;IAClE,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,IAAI,8BAA8B;CAClE,CAAC;AAEF,MAAM,2BAA4B,SAAQ,uBAAU;IAC3C,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI;QAC5C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,OAAO,GAAG,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,iBAAiB,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC;IACnG,CAAC;CACF;AAED,MAAa,qBAAsB,SAAQ,uCAAkB;IAC3C,SAAS,CAAC,MAAM;QAC9B,OAAO,IAAI,2BAA2B,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACvD,CAAC;IAEe,gBAAgB,CAAC,IAAI,EAAE,QAAQ;QAC7C,OAAO,YAAY,IAAI,cAAc,QAAQ,GAAG,CAAC;IACnD,CAAC;IAEe,WAAW,CAAC,IAAI,EAAE,QAAQ;QACxC,OAAO,YAAY,IAAI,cAAc,QAAQ,GAAG,CAAC;IACnD,CAAC;IAEe,iBAAiB,CAAC,WAAW,EAAE,SAAS;QACtD,OAAO,uBAAuB,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC;IACzD,CAAC;IAEe,gBAAgB;QAC9B,OAAO,2BAA2B,CAAC;IACrC,CAAC;CACF;AApBD,sDAoBC"}
|
|
@@ -30,7 +30,7 @@ export declare class BaseMeasure {
|
|
|
30
30
|
isAdditive(): boolean;
|
|
31
31
|
static isCumulative(definition: any): boolean;
|
|
32
32
|
rollingWindowDefinition(): any;
|
|
33
|
-
dateJoinCondition(): (import("./BaseTimeDimension").BaseTimeDimension | ((dateFrom: any, dateTo: any, dateField: any,
|
|
33
|
+
dateJoinCondition(): (import("./BaseTimeDimension").BaseTimeDimension | ((dateFrom: any, dateTo: any, dateField: any, _dimensionDateFrom: any, _dimensionDateTo: any, _isFromStartToEnd: any) => string))[][] | null;
|
|
34
34
|
windowGranularity(): any;
|
|
35
35
|
minGranularity(granularityA: string | undefined, granularityB: string | undefined): any;
|
|
36
36
|
granularityFromInterval(interval: string): "day" | "hour" | "week" | "month" | "year" | undefined;
|
|
@@ -79,7 +79,14 @@ export class BaseQuery {
|
|
|
79
79
|
/** @type {import('../compiler/JoinGraph').JoinGraph} */
|
|
80
80
|
joinGraph: import('../compiler/JoinGraph').JoinGraph;
|
|
81
81
|
options: any;
|
|
82
|
-
|
|
82
|
+
/**
|
|
83
|
+
* @param {{ id: string, desc: boolean }} hash
|
|
84
|
+
* @returns {string|null}
|
|
85
|
+
*/
|
|
86
|
+
orderHashToString(hash: {
|
|
87
|
+
id: string;
|
|
88
|
+
desc: boolean;
|
|
89
|
+
}): string | null;
|
|
83
90
|
defaultOrder(): {
|
|
84
91
|
id: any;
|
|
85
92
|
desc: boolean;
|
|
@@ -237,9 +244,9 @@ export class BaseQuery {
|
|
|
237
244
|
*/
|
|
238
245
|
buildLambdaQuery(): Record<string, Array<string>>;
|
|
239
246
|
externalQuery(): any;
|
|
240
|
-
runningTotalDateJoinCondition(): (BaseTimeDimension | ((
|
|
241
|
-
rollingWindowToDateJoinCondition(granularity: any): (BaseTimeDimension | ((dateFrom: any, dateTo: any, dateField: any,
|
|
242
|
-
rollingWindowDateJoinCondition(trailingInterval: any, leadingInterval: any, offset: any): (BaseTimeDimension | ((dateFrom: any, dateTo: any, dateField: any,
|
|
247
|
+
runningTotalDateJoinCondition(): (BaseTimeDimension | ((_dateFrom: any, dateTo: any, dateField: any, dimensionDateFrom: any, _dimensionDateTo: any) => string))[][];
|
|
248
|
+
rollingWindowToDateJoinCondition(granularity: any): (BaseTimeDimension | ((dateFrom: any, dateTo: any, dateField: any, _dimensionDateFrom: any, _dimensionDateTo: any, _isFromStartToEnd: any) => string))[][];
|
|
249
|
+
rollingWindowDateJoinCondition(trailingInterval: any, leadingInterval: any, offset: any): (BaseTimeDimension | ((dateFrom: any, dateTo: any, dateField: any, _dimensionDateFrom: any, _dimensionDateTo: any, isFromStartToEnd: any) => string))[][];
|
|
243
250
|
/**
|
|
244
251
|
* @param {string} date
|
|
245
252
|
* @param {string} interval
|
|
@@ -306,7 +313,12 @@ export class BaseQuery {
|
|
|
306
313
|
overTimeSeriesQuery(baseQueryFn: any, cumulativeMeasure: any, fromRollup: any): any;
|
|
307
314
|
overTimeSeriesSelect(cumulativeMeasures: any, dateSeriesSql: any, baseQuery: any, dateJoinConditionSql: any, baseQueryAlias: any, dateSeriesGranularity: any): string;
|
|
308
315
|
overTimeSeriesForSelect(cumulativeMeasures: any, dateSeriesGranularity: any): string;
|
|
309
|
-
|
|
316
|
+
/**
|
|
317
|
+
* BigQuery has strict date type and can not automatically convert between date
|
|
318
|
+
* and timestamp, so we override dateFromStartToEndConditionSql() in BigQuery Dialect
|
|
319
|
+
* @protected
|
|
320
|
+
*/
|
|
321
|
+
protected dateFromStartToEndConditionSql(dateJoinCondition: any, fromRollup: any, isFromStartToEnd: any): any;
|
|
310
322
|
/**
|
|
311
323
|
* @param {import('./BaseTimeDimension').BaseTimeDimension} timeDimension
|
|
312
324
|
* @return {string}
|
|
@@ -410,6 +422,17 @@ export class BaseQuery {
|
|
|
410
422
|
* @returns {Array<Array<string>>}
|
|
411
423
|
*/
|
|
412
424
|
collectJoinHints(excludeTimeDimensions?: boolean | undefined): Array<Array<string>>;
|
|
425
|
+
joinMembersFromCustomSubQuery(): {
|
|
426
|
+
getMembers: () => {
|
|
427
|
+
path: () => null;
|
|
428
|
+
cube: () => any;
|
|
429
|
+
definition: () => {
|
|
430
|
+
sql: Function;
|
|
431
|
+
type: string;
|
|
432
|
+
};
|
|
433
|
+
}[];
|
|
434
|
+
}[];
|
|
435
|
+
joinMembersFromJoin(join: any): any;
|
|
413
436
|
collectJoinHintsFromMembers(members: any): any[];
|
|
414
437
|
collectFromMembers(excludeTimeDimensions: any, fn: any, methodName: any): any[];
|
|
415
438
|
/**
|
|
@@ -433,11 +456,18 @@ export class BaseQuery {
|
|
|
433
456
|
*/
|
|
434
457
|
groupByClause(): string;
|
|
435
458
|
/**
|
|
436
|
-
* XXX: String as return value is added because of HiveQuery.getFieldIndex()
|
|
437
|
-
* @
|
|
459
|
+
* XXX: String as return value is added because of HiveQuery.getFieldIndex() and DatabricksQuery.getFieldIndex()
|
|
460
|
+
* @protected
|
|
461
|
+
* @param {string} id member name in form of "cube.member[.granularity]"
|
|
438
462
|
* @returns {number|string|null}
|
|
439
463
|
*/
|
|
440
|
-
getFieldIndex(id:
|
|
464
|
+
protected getFieldIndex(id: string): number | string | null;
|
|
465
|
+
/**
|
|
466
|
+
* @protected
|
|
467
|
+
* @param {string} id member name in form of "cube.member[.granularity]"
|
|
468
|
+
* @returns {null|string}
|
|
469
|
+
*/
|
|
470
|
+
protected getFieldAlias(id: string): null | string;
|
|
441
471
|
orderBy(): string;
|
|
442
472
|
/**
|
|
443
473
|
* Returns a complete list of the aliased dimensions, including time
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseQuery.d.ts","sourceRoot":"","sources":["../../../src/adapter/BaseQuery.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BaseQuery.d.ts","sourceRoot":"","sources":["../../../src/adapter/BaseQuery.js"],"names":[],"mappings":"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"}
|
|
@@ -377,10 +377,67 @@ class BaseQuery {
|
|
|
377
377
|
*/
|
|
378
378
|
get allJoinHints() {
|
|
379
379
|
if (!this.collectedJoinHints) {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
380
|
+
const [rootOfJoin, ...allMembersJoinHints] = this.collectJoinHintsFromMembers(this.allMembersConcat(false));
|
|
381
|
+
const customSubQueryJoinHints = this.collectJoinHintsFromMembers(this.joinMembersFromCustomSubQuery());
|
|
382
|
+
let joinMembersJoinHints = this.collectJoinHintsFromMembers(this.joinMembersFromJoin(this.join));
|
|
383
|
+
// One cube may join the other cube via transitive joined cubes,
|
|
384
|
+
// members from which are referenced in the join `on` clauses.
|
|
385
|
+
// We need to collect such join hints and push them upfront of the joining one
|
|
386
|
+
// but only if they don't exist yet. Cause in other case we might affect what
|
|
387
|
+
// join path will be constructed in join graph.
|
|
388
|
+
// It is important to use queryLevelJoinHints during the calculation if it is set.
|
|
389
|
+
const constructJH = () => {
|
|
390
|
+
const filteredJoinMembersJoinHints = joinMembersJoinHints.filter(m => !allMembersJoinHints.includes(m));
|
|
391
|
+
return [
|
|
392
|
+
...this.queryLevelJoinHints,
|
|
393
|
+
...(rootOfJoin ? [rootOfJoin] : []),
|
|
394
|
+
...filteredJoinMembersJoinHints,
|
|
395
|
+
...allMembersJoinHints,
|
|
396
|
+
...customSubQueryJoinHints,
|
|
397
|
+
];
|
|
398
|
+
};
|
|
399
|
+
let prevJoins = this.join;
|
|
400
|
+
let prevJoinMembersJoinHints = joinMembersJoinHints;
|
|
401
|
+
let newJoin = this.joinGraph.buildJoin(constructJH());
|
|
402
|
+
const isOrderPreserved = (base, updated) => {
|
|
403
|
+
const common = base.filter(value => updated.includes(value));
|
|
404
|
+
const bFiltered = updated.filter(value => common.includes(value));
|
|
405
|
+
return common.every((x, i) => x === bFiltered[i]);
|
|
406
|
+
};
|
|
407
|
+
const isJoinTreesEqual = (a, b) => {
|
|
408
|
+
if (!a || !b || a.root !== b.root || a.joins.length !== b.joins.length) {
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
// We don't care about the order of joins on the same level, so
|
|
412
|
+
// we can compare them as sets.
|
|
413
|
+
const aJoinsSet = new Set(a.joins.map(j => `${j.originalFrom}->${j.originalTo}`));
|
|
414
|
+
const bJoinsSet = new Set(b.joins.map(j => `${j.originalFrom}->${j.originalTo}`));
|
|
415
|
+
if (aJoinsSet.size !== bJoinsSet.size) {
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
for (const val of aJoinsSet) {
|
|
419
|
+
if (!bJoinsSet.has(val)) {
|
|
420
|
+
return false;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return true;
|
|
424
|
+
};
|
|
425
|
+
// Safeguard against infinite loop in case of cyclic joins somehow managed to slip through
|
|
426
|
+
let cnt = 0;
|
|
427
|
+
while (newJoin?.joins.length > 0 && !isJoinTreesEqual(prevJoins, newJoin) && cnt < 10000) {
|
|
428
|
+
prevJoins = newJoin;
|
|
429
|
+
joinMembersJoinHints = this.collectJoinHintsFromMembers(this.joinMembersFromJoin(newJoin));
|
|
430
|
+
if (!isOrderPreserved(prevJoinMembersJoinHints, joinMembersJoinHints)) {
|
|
431
|
+
throw new UserError_1.UserError(`Can not construct joins for the query, potential loop detected: ${prevJoinMembersJoinHints.join('->')} vs ${joinMembersJoinHints.join('->')}`);
|
|
432
|
+
}
|
|
433
|
+
newJoin = this.joinGraph.buildJoin(constructJH());
|
|
434
|
+
prevJoinMembersJoinHints = joinMembersJoinHints;
|
|
435
|
+
cnt++;
|
|
436
|
+
}
|
|
437
|
+
if (cnt >= 10000) {
|
|
438
|
+
throw new UserError_1.UserError('Can not construct joins for the query, potential loop detected');
|
|
439
|
+
}
|
|
440
|
+
this.collectedJoinHints = ramda_1.default.uniq(constructJH());
|
|
384
441
|
}
|
|
385
442
|
return this.collectedJoinHints;
|
|
386
443
|
}
|
|
@@ -447,8 +504,9 @@ class BaseQuery {
|
|
|
447
504
|
res.push({ id, desc: true });
|
|
448
505
|
}
|
|
449
506
|
else if (this.dimensions.length > 0) {
|
|
507
|
+
const dim = this.dimensions[0];
|
|
450
508
|
res.push({
|
|
451
|
-
id:
|
|
509
|
+
id: dim.expressionName ?? dim.dimension,
|
|
452
510
|
desc: false,
|
|
453
511
|
});
|
|
454
512
|
}
|
|
@@ -800,8 +858,7 @@ class BaseQuery {
|
|
|
800
858
|
return this.timeDimensions
|
|
801
859
|
.map(d => [
|
|
802
860
|
d,
|
|
803
|
-
|
|
804
|
-
(dateFrom, dateTo, dateField, dimensionDateFrom, dimensionDateTo) => `${dateField} >= ${dimensionDateFrom} AND ${dateField} <= ${dateTo}`
|
|
861
|
+
(_dateFrom, dateTo, dateField, dimensionDateFrom, _dimensionDateTo) => `${dateField} >= ${dimensionDateFrom} AND ${dateField} <= ${dateTo}`
|
|
805
862
|
]);
|
|
806
863
|
}
|
|
807
864
|
rollingWindowToDateJoinCondition(granularity) {
|
|
@@ -809,14 +866,14 @@ class BaseQuery {
|
|
|
809
866
|
.filter(td => td.granularity)
|
|
810
867
|
.map(d => [
|
|
811
868
|
d,
|
|
812
|
-
(dateFrom, dateTo, dateField,
|
|
869
|
+
(dateFrom, dateTo, dateField, _dimensionDateFrom, _dimensionDateTo, _isFromStartToEnd) => `${dateField} >= ${this.timeGroupedColumn(granularity, dateFrom)} AND ${dateField} <= ${dateTo}`
|
|
813
870
|
]);
|
|
814
871
|
}
|
|
815
872
|
rollingWindowDateJoinCondition(trailingInterval, leadingInterval, offset) {
|
|
816
873
|
offset = offset || 'end';
|
|
817
874
|
return this.timeDimensions
|
|
818
875
|
.filter(td => td.granularity)
|
|
819
|
-
.map(d => [d, (dateFrom, dateTo, dateField,
|
|
876
|
+
.map(d => [d, (dateFrom, dateTo, dateField, _dimensionDateFrom, _dimensionDateTo, isFromStartToEnd) => {
|
|
820
877
|
// dateFrom based window
|
|
821
878
|
const conditions = [];
|
|
822
879
|
if (trailingInterval !== 'unbounded') {
|
|
@@ -1409,7 +1466,15 @@ class BaseQuery {
|
|
|
1409
1466
|
.concat(this.dateFromStartToEndConditionSql(uniqDateJoinCondition, fromRollup, true));
|
|
1410
1467
|
const baseQuery = this.groupedUngroupedSelect(() => baseQueryFn(cumulativeMeasures, filters), cumulativeMeasure.shouldUngroupForCumulative(), !cumulativeMeasure.shouldUngroupForCumulative() && this.minGranularity(cumulativeMeasure.windowGranularity(), dateSeriesGranularity) || undefined);
|
|
1411
1468
|
const baseQueryAlias = this.cubeAlias('base');
|
|
1412
|
-
const dateJoinConditionSql = dateJoinCondition.map(([d, f]) => f(
|
|
1469
|
+
const dateJoinConditionSql = dateJoinCondition.map(([d, f]) => f(
|
|
1470
|
+
// Time-series table is generated differently in different dialects,
|
|
1471
|
+
// but some dialects (like BigQuery) require strict date types and can not automatically convert
|
|
1472
|
+
// between date and timestamp for comparisons, at the same time, time dimensions are expected to be
|
|
1473
|
+
// timestamps, so we need to align types for join conditions/comparisons.
|
|
1474
|
+
// But we can't do it here, as it would break interval maths used in some types of
|
|
1475
|
+
// rolling window join conditions in some dialects (like Redshift), so we need to
|
|
1476
|
+
// do casts granularly in rolling window join conditions functions.
|
|
1477
|
+
`${d.dateSeriesAliasName()}.${this.escapeColumnName('date_from')}`, `${d.dateSeriesAliasName()}.${this.escapeColumnName('date_to')}`, `${baseQueryAlias}.${d.aliasName()}`, `'${d.dateFromFormatted()}'`, `'${d.dateToFormatted()}'`)).join(' AND ');
|
|
1413
1478
|
return this.overTimeSeriesSelect(cumulativeMeasures, dateSeriesSql, baseQuery, dateJoinConditionSql, baseQueryAlias, dateSeriesDimension.granularity);
|
|
1414
1479
|
}
|
|
1415
1480
|
overTimeSeriesSelect(cumulativeMeasures, dateSeriesSql, baseQuery, dateJoinConditionSql, baseQueryAlias, dateSeriesGranularity) {
|
|
@@ -1426,9 +1491,13 @@ class BaseQuery {
|
|
|
1426
1491
|
.filter(c => !!c)
|
|
1427
1492
|
.join(', ');
|
|
1428
1493
|
}
|
|
1494
|
+
/**
|
|
1495
|
+
* BigQuery has strict date type and can not automatically convert between date
|
|
1496
|
+
* and timestamp, so we override dateFromStartToEndConditionSql() in BigQuery Dialect
|
|
1497
|
+
* @protected
|
|
1498
|
+
*/
|
|
1429
1499
|
dateFromStartToEndConditionSql(dateJoinCondition, fromRollup, isFromStartToEnd) {
|
|
1430
1500
|
return dateJoinCondition.map(
|
|
1431
|
-
// TODO these weird conversions to be strict typed for big query.
|
|
1432
1501
|
// TODO Consider adding strict definitions of local and UTC time type
|
|
1433
1502
|
([d, f]) => ({
|
|
1434
1503
|
filterToWhere: () => {
|
|
@@ -1855,7 +1924,17 @@ class BaseQuery {
|
|
|
1855
1924
|
return [s.patchedMeasure.patchedFrom.cubeName].concat(this.evaluateSymbolSql(s.patchedMeasure.patchedFrom.cubeName, s.patchedMeasure.patchedFrom.name, s.definition()));
|
|
1856
1925
|
}
|
|
1857
1926
|
else {
|
|
1858
|
-
|
|
1927
|
+
const res = this.evaluateSql(s.cube().name, s.definition().sql);
|
|
1928
|
+
if (s.isJoinCondition) {
|
|
1929
|
+
// In a join between Cube A and Cube B, sql() may reference members from other cubes.
|
|
1930
|
+
// These referenced cubes must be added as join hints before Cube B to ensure correct SQL generation.
|
|
1931
|
+
const targetCube = s.targetCubeName();
|
|
1932
|
+
let { joinHints } = this.safeEvaluateSymbolContext();
|
|
1933
|
+
joinHints = joinHints.filter(e => e !== targetCube);
|
|
1934
|
+
joinHints.push(targetCube);
|
|
1935
|
+
this.safeEvaluateSymbolContext().joinHints = joinHints;
|
|
1936
|
+
}
|
|
1937
|
+
return res;
|
|
1859
1938
|
}
|
|
1860
1939
|
}
|
|
1861
1940
|
/**
|
|
@@ -1871,7 +1950,15 @@ class BaseQuery {
|
|
|
1871
1950
|
* @returns {Array<Array<string>>}
|
|
1872
1951
|
*/
|
|
1873
1952
|
collectJoinHints(excludeTimeDimensions = false) {
|
|
1874
|
-
const
|
|
1953
|
+
const membersToCollectFrom = [
|
|
1954
|
+
...this.allMembersConcat(excludeTimeDimensions),
|
|
1955
|
+
...this.joinMembersFromJoin(this.join),
|
|
1956
|
+
...this.joinMembersFromCustomSubQuery(),
|
|
1957
|
+
];
|
|
1958
|
+
return this.collectJoinHintsFromMembers(membersToCollectFrom);
|
|
1959
|
+
}
|
|
1960
|
+
joinMembersFromCustomSubQuery() {
|
|
1961
|
+
return this.customSubQueryJoins.map(j => {
|
|
1875
1962
|
const res = {
|
|
1876
1963
|
path: () => null,
|
|
1877
1964
|
cube: () => this.cubeEvaluator.cubeFromPath(j.on.cubeName),
|
|
@@ -1885,19 +1972,17 @@ class BaseQuery {
|
|
|
1885
1972
|
getMembers: () => [res],
|
|
1886
1973
|
};
|
|
1887
1974
|
});
|
|
1888
|
-
|
|
1975
|
+
}
|
|
1976
|
+
joinMembersFromJoin(join) {
|
|
1977
|
+
return join ? join.joins.map(j => ({
|
|
1889
1978
|
getMembers: () => [{
|
|
1890
1979
|
path: () => null,
|
|
1891
1980
|
cube: () => this.cubeEvaluator.cubeFromPath(j.originalFrom),
|
|
1892
1981
|
definition: () => j.join,
|
|
1982
|
+
isJoinCondition: true,
|
|
1983
|
+
targetCubeName: () => j.originalTo,
|
|
1893
1984
|
}]
|
|
1894
1985
|
})) : [];
|
|
1895
|
-
const membersToCollectFrom = [
|
|
1896
|
-
...this.allMembersConcat(excludeTimeDimensions),
|
|
1897
|
-
...joinMembers,
|
|
1898
|
-
...customSubQueryJoinMembers,
|
|
1899
|
-
];
|
|
1900
|
-
return this.collectJoinHintsFromMembers(membersToCollectFrom);
|
|
1901
1986
|
}
|
|
1902
1987
|
collectJoinHintsFromMembers(members) {
|
|
1903
1988
|
return [
|
|
@@ -1966,20 +2051,38 @@ class BaseQuery {
|
|
|
1966
2051
|
return this.rollupGroupByClause(dimensionNames);
|
|
1967
2052
|
}
|
|
1968
2053
|
/**
|
|
1969
|
-
* XXX: String as return value is added because of HiveQuery.getFieldIndex()
|
|
1970
|
-
* @
|
|
2054
|
+
* XXX: String as return value is added because of HiveQuery.getFieldIndex() and DatabricksQuery.getFieldIndex()
|
|
2055
|
+
* @protected
|
|
2056
|
+
* @param {string} id member name in form of "cube.member[.granularity]"
|
|
1971
2057
|
* @returns {number|string|null}
|
|
1972
2058
|
*/
|
|
1973
2059
|
getFieldIndex(id) {
|
|
1974
2060
|
const equalIgnoreCase = (a, b) => (typeof a === 'string' && typeof b === 'string' && a.toUpperCase() === b.toUpperCase());
|
|
1975
|
-
let index;
|
|
1976
|
-
|
|
2061
|
+
let index = -1;
|
|
2062
|
+
const path = id.split('.');
|
|
2063
|
+
// Granularity is specified
|
|
2064
|
+
if (path.length === 3) {
|
|
2065
|
+
const memberName = path.slice(0, 2).join('.');
|
|
2066
|
+
const granularity = path[2];
|
|
2067
|
+
index = this.timeDimensions
|
|
2068
|
+
// Not all time dimensions are used in select list, some are just filters,
|
|
2069
|
+
// but they exist in this.timeDimensions, so need to filter them out
|
|
2070
|
+
.filter(d => d.selectColumns())
|
|
2071
|
+
.findIndex(d => ((equalIgnoreCase(d.dimension, memberName) && (d.granularityObj?.granularity === granularity)) ||
|
|
2072
|
+
equalIgnoreCase(d.expressionName, memberName)));
|
|
2073
|
+
if (index > -1) {
|
|
2074
|
+
return index + 1;
|
|
2075
|
+
}
|
|
2076
|
+
// TODO IT would be nice to log a warning that requested member wasn't found, but we don't have a logger here
|
|
2077
|
+
return null;
|
|
2078
|
+
}
|
|
2079
|
+
const dimensionsForSelect = this.dimensionsForSelect()
|
|
1977
2080
|
// Not all time dimensions are used in select list, some are just filters,
|
|
1978
2081
|
// but they exist in this.timeDimensions, so need to filter them out
|
|
1979
|
-
.filter(d => d.selectColumns())
|
|
1980
|
-
|
|
1981
|
-
if (index > -1) {
|
|
1982
|
-
return index + 1;
|
|
2082
|
+
.filter(d => d.selectColumns());
|
|
2083
|
+
const found = (0, shared_1.findMinGranularityDimension)(id, dimensionsForSelect);
|
|
2084
|
+
if (found?.index > -1) {
|
|
2085
|
+
return found.index + 1;
|
|
1983
2086
|
}
|
|
1984
2087
|
index = this.measures.findIndex(d => equalIgnoreCase(d.measure, id) || equalIgnoreCase(d.expressionName, id));
|
|
1985
2088
|
if (index > -1) {
|
|
@@ -1988,6 +2091,48 @@ class BaseQuery {
|
|
|
1988
2091
|
}
|
|
1989
2092
|
return null;
|
|
1990
2093
|
}
|
|
2094
|
+
/**
|
|
2095
|
+
* @protected
|
|
2096
|
+
* @param {string} id member name in form of "cube.member[.granularity]"
|
|
2097
|
+
* @returns {null|string}
|
|
2098
|
+
*/
|
|
2099
|
+
getFieldAlias(id) {
|
|
2100
|
+
const equalIgnoreCase = (a, b) => (typeof a === 'string' && typeof b === 'string' && a.toUpperCase() === b.toUpperCase());
|
|
2101
|
+
let field;
|
|
2102
|
+
const path = id.split('.');
|
|
2103
|
+
// Granularity is specified
|
|
2104
|
+
if (path.length === 3) {
|
|
2105
|
+
const memberName = path.slice(0, 2).join('.');
|
|
2106
|
+
const granularity = path[2];
|
|
2107
|
+
field = this.timeDimensions
|
|
2108
|
+
// Not all time dimensions are used in select list, some are just filters,
|
|
2109
|
+
// but they exist in this.timeDimensions, so need to filter them out
|
|
2110
|
+
.filter(d => d.selectColumns())
|
|
2111
|
+
.find(d => ((equalIgnoreCase(d.dimension, memberName) && (d.granularityObj?.granularity === granularity)) ||
|
|
2112
|
+
equalIgnoreCase(d.expressionName, memberName)));
|
|
2113
|
+
if (field) {
|
|
2114
|
+
return field.aliasName();
|
|
2115
|
+
}
|
|
2116
|
+
return null;
|
|
2117
|
+
}
|
|
2118
|
+
const dimensionsForSelect = this.dimensionsForSelect()
|
|
2119
|
+
// Not all time dimensions are used in select list, some are just filters,
|
|
2120
|
+
// but they exist in this.timeDimensions, so need to filter them out
|
|
2121
|
+
.filter(d => d.selectColumns());
|
|
2122
|
+
const found = (0, shared_1.findMinGranularityDimension)(id, dimensionsForSelect);
|
|
2123
|
+
if (found?.dimension) {
|
|
2124
|
+
return found.dimension.aliasName();
|
|
2125
|
+
}
|
|
2126
|
+
field = this.measures.find((d) => equalIgnoreCase(d.measure, id) || equalIgnoreCase(d.expressionName, id));
|
|
2127
|
+
if (field) {
|
|
2128
|
+
return field.aliasName();
|
|
2129
|
+
}
|
|
2130
|
+
return null;
|
|
2131
|
+
}
|
|
2132
|
+
/**
|
|
2133
|
+
* @param {{ id: string, desc: boolean }} hash
|
|
2134
|
+
* @returns {string|null}
|
|
2135
|
+
*/
|
|
1991
2136
|
orderHashToString(hash) {
|
|
1992
2137
|
if (!hash || !hash.id) {
|
|
1993
2138
|
return null;
|
|
@@ -2137,7 +2282,7 @@ class BaseQuery {
|
|
|
2137
2282
|
}
|
|
2138
2283
|
pushJoinHints(joinHints) {
|
|
2139
2284
|
if (this.safeEvaluateSymbolContext().joinHints && joinHints) {
|
|
2140
|
-
if (joinHints.length === 1) {
|
|
2285
|
+
if (Array.isArray(joinHints) && joinHints.length === 1) {
|
|
2141
2286
|
[joinHints] = joinHints;
|
|
2142
2287
|
}
|
|
2143
2288
|
this.safeEvaluateSymbolContext().joinHints.push(joinHints);
|
|
@@ -3105,6 +3250,7 @@ class BaseQuery {
|
|
|
3105
3250
|
like_escape: '{{ like_expr }} ESCAPE {{ escape_char }}',
|
|
3106
3251
|
within_group: '{{ fun_sql }} WITHIN GROUP (ORDER BY {{ within_group_concat }})',
|
|
3107
3252
|
concat_strings: '{{ strings | join(\' || \' ) }}',
|
|
3253
|
+
rolling_window_expr_timestamp_cast: '{{ value }}'
|
|
3108
3254
|
},
|
|
3109
3255
|
tesseract: {
|
|
3110
3256
|
ilike: '{{ expr }} {% if negated %}NOT {% endif %}ILIKE {{ pattern }}', // May require different overloads in Tesseract than the ilike from expressions used in SQLAPI.
|