Skip to content

Commit ed9dfb4

Browse files
committed
in work
1 parent 3e9f6db commit ed9dfb4

File tree

11 files changed

+435
-57
lines changed

11 files changed

+435
-57
lines changed

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

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { BaseTimeDimension } from './BaseTimeDimension';
3636
import { Granularity } from './Granularity';
3737
import { ParamAllocator } from './ParamAllocator';
3838
import { PreAggregations } from './PreAggregations';
39+
import { parseSqlInterval } from '@cubejs-backend/shared';
3940

4041
const DEFAULT_PREAGGREGATIONS_SCHEMA = 'stb_pre_aggregations';
4142

@@ -760,7 +761,7 @@ export class BaseQuery {
760761
}
761762
}
762763

763-
return this.compilers.compiler.withQuery(
764+
const res = this.compilers.compiler.withQuery(
764765
this,
765766
() => this.cacheValue(
766767
['buildSqlAndParams', exportAnnotatedSql],
@@ -772,6 +773,8 @@ export class BaseQuery {
772773
{ cache: this.queryCache }
773774
)
774775
);
776+
console.log("!!!! old res ", res[0]);
777+
return res;
775778
}
776779

777780
buildSqlAndParamsRust(exportAnnotatedSql) {
@@ -816,6 +819,7 @@ export class BaseQuery {
816819
if (preAggregation) {
817820
this.preAggregations.preAggregationForQuery = preAggregation;
818821
}
822+
console.log("!!!! new res ", query);
819823
return [query, paramsArray];
820824
}
821825

@@ -1890,6 +1894,64 @@ export class BaseQuery {
18901894
return `${value}::timestamp`;
18911895
}
18921896

1897+
/**
1898+
* Converts the input interval (e.g. "2 years", "3 months", "5 days")
1899+
* into a format compatible with the target SQL dialect.
1900+
* Also returns the minimal time unit required (e.g. for use in DATEDIFF).
1901+
*
1902+
* Returns a tuple: (formatted interval, minimal time unit)
1903+
*/
1904+
intervalAndMinimalTimeUnit(interval) {
1905+
const intervalParsed = parseSqlInterval(interval);
1906+
const intKeys = Object.keys(intervalParsed).length;
1907+
1908+
if (intervalParsed.year && intKeys === 1) {
1909+
return [interval, 'year'];
1910+
} else if (intervalParsed.year && intervalParsed.month && intKeys === 2) {
1911+
return [interval, 'month'];
1912+
} else if (intervalParsed.year && intervalParsed.month && intervalParsed.day && intKeys === 3) {
1913+
return [interval, 'day'];
1914+
} else if (intervalParsed.year && intervalParsed.month && intervalParsed.day && intervalParsed.hour && intKeys === 4) {
1915+
return [interval, 'hour'];
1916+
} else if (intervalParsed.year && intervalParsed.month && intervalParsed.day && intervalParsed.hour && intervalParsed.minute && intKeys === 5) {
1917+
return [interval, 'minute'];
1918+
} else if (intervalParsed.year && intervalParsed.month && intervalParsed.day && intervalParsed.hour && intervalParsed.minute && intervalParsed.second && intKeys === 6) {
1919+
return [interval, 'second'];
1920+
} else if (intervalParsed.quarter && intKeys === 1) {
1921+
return [interval, 'quarter'];
1922+
} else if (intervalParsed.month && intKeys === 1) {
1923+
return [interval, 'month'];
1924+
} else if (intervalParsed.month && intervalParsed.day && intKeys === 2) {
1925+
return [interval, 'day'];
1926+
} else if (intervalParsed.month && intervalParsed.day && intervalParsed.hour && intKeys === 3) {
1927+
return [interval, 'hour'];
1928+
} else if (intervalParsed.month && intervalParsed.day && intervalParsed.hour && intervalParsed.minute && intKeys === 4) {
1929+
return [interval, 'minute'];
1930+
} else if (intervalParsed.month && intervalParsed.day && intervalParsed.hour && intervalParsed.minute && intervalParsed.second && intKeys === 5) {
1931+
return [interval, 'second'];
1932+
} else if (intervalParsed.week && intKeys === 1) {
1933+
return [interval, 'week'];
1934+
} else if (intervalParsed.day && intKeys === 1) {
1935+
return [interval, 'day'];
1936+
} else if (intervalParsed.day && intervalParsed.hour && intKeys === 2) {
1937+
return [interval, 'hour'];
1938+
} else if (intervalParsed.day && intervalParsed.hour && intervalParsed.minute && intKeys === 3) {
1939+
return [interval, 'minute'];
1940+
} else if (intervalParsed.day && intervalParsed.hour && intervalParsed.minute && intervalParsed.second && intKeys === 4) {
1941+
return [interval, 'second'];
1942+
} else if (intervalParsed.hour && intervalParsed.minute && intKeys === 2) {
1943+
return [interval, 'minute'];
1944+
} else if (intervalParsed.hour && intervalParsed.minute && intervalParsed.second && intKeys === 3) {
1945+
return [interval, 'second'];
1946+
} else if (intervalParsed.minute && intervalParsed.second && intKeys === 2) {
1947+
return [interval, 'second'];
1948+
}
1949+
1950+
// No need to support microseconds.
1951+
1952+
throw new Error(`Cannot transform interval expression "${interval}"`);
1953+
}
1954+
18931955
commonQuery() {
18941956
return `SELECT${this.topLimit()}
18951957
${this.baseSelect()}

packages/cubejs-schema-compiler/src/adapter/BigqueryQuery.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export class BigqueryQuery extends BaseQuery {
8383
* @see https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#interval_type
8484
* It returns a tuple of (formatted interval, timeUnit to use in datediff functions)
8585
*/
86-
private formatInterval(interval: string): [string, string] {
86+
public formatInterval(interval: string): [string, string] {
8787
const intervalParsed = parseSqlInterval(interval);
8888
const intKeys = Object.keys(intervalParsed).length;
8989

@@ -134,6 +134,10 @@ export class BigqueryQuery extends BaseQuery {
134134
throw new Error(`Cannot transform interval expression "${interval}" to BigQuery dialect`);
135135
}
136136

137+
public intervalAndMinimalTimeUnit(interval: string): [string, string] {
138+
return this.formatInterval(interval);
139+
}
140+
137141
public newFilter(filter) {
138142
return new BigqueryFilter(this, filter);
139143
}
@@ -278,7 +282,25 @@ export class BigqueryQuery extends BaseQuery {
278282
'{% if not loop.last %} UNION ALL\n{% endif %}' +
279283
'{% endfor %}' +
280284
') AS dates';
281-
285+
templates.statements.generated_time_series_select = 'SELECT DATETIME(d) AS date_from,\n' +
286+
'DATETIME_SUB(DATETIME_ADD(DATETIME(d), INTERVAL {{ granularity }}), INTERVAL 1 MILLISECOND) AS date_to \n' +
287+
'FROM UNNEST(\n' +
288+
'{% if minimal_time_unit|upper in ["DAY", "WEEK", "MONTH", "QUARTER", "YEAR"] %}' +
289+
'GENERATE_DATE_ARRAY(DATE({{ start }}), DATE({{ end }}), INTERVAL {{ granularity }})\n' +
290+
'{% else %}' +
291+
'GENERATE_TIMESTAMP_ARRAY(TIMESTAMP({{ start }}), TIMESTAMP({{ end }}), INTERVAL {{ granularity }})\n' +
292+
'{% endif %}' +
293+
') AS d';
294+
295+
templates.statements.generated_time_series_with_cte_range_source = 'SELECT DATETIME(d) AS date_from,\n' +
296+
'DATETIME_SUB(DATETIME_ADD(DATETIME(d), INTERVAL {{ granularity }}), INTERVAL 1 MILLISECOND) AS date_to \n' +
297+
'FROM {{ range_source }}, UNNEST(\n' +
298+
'{% if minimal_time_unit|upper in ["DAY", "WEEK", "MONTH", "QUARTER", "YEAR"] %}' +
299+
'GENERATE_DATE_ARRAY(DATE({{ range_source }}.{{ min_name }}), DATE({{ range_source }}.{{ max_name }}), INTERVAL {{ granularity }})\n' +
300+
'{% else %}' +
301+
'GENERATE_TIMESTAMP_ARRAY(TIMESTAMP({{ range_source }}.{{ min_name }}), TIMESTAMP({{ range_source }}.{{ max_name }}), INTERVAL {{ granularity }})\n' +
302+
'{% endif %}' +
303+
') AS d';
282304
return templates;
283305
}
284306
}

packages/cubejs-schema-compiler/src/adapter/PostgresQuery.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,12 @@ export class PostgresQuery extends BaseQuery {
8282
templates.types.double = 'DOUBLE PRECISION';
8383
templates.types.binary = 'BYTEA';
8484
templates.operators.is_not_distinct_from = 'IS NOT DISTINCT FROM';
85-
templates.statements.generated_time_series_select = 'SELECT date_from AS "date_from",\n' +
86-
'date_from + interval \'{{ granularity }}\' - interval \'1 millisecond\' AS "date_to" \n' +
87-
'FROM generate_series({{ start }}::timestamp, {{ end }}:: timestamp, \'{{ granularity }}\'::interval) "date_from" ';
85+
templates.statements.generated_time_series_select = 'SELECT d AS "date_from",\n' +
86+
'd + interval \'{{ granularity }}\' - interval \'1 millisecond\' AS "date_to" \n' +
87+
'FROM generate_series({{ start }}::timestamp, {{ end }}:: timestamp, \'{{ granularity }}\'::interval) d ';
88+
templates.statements.generated_time_series_with_cte_range_source = 'SELECT d AS "date_from",\n' +
89+
'd + interval \'{{ granularity }}\' - interval \'1 millisecond\' AS "date_to" \n' +
90+
'FROM {{ range_source }}, LATERAL generate_series({{ range_source }}.{{ min_name }}, {{ range_source }}.{{ max_name }}, \'{{ granularity }}\'::interval) d ';
8891
return templates;
8992
}
9093

packages/cubejs-testing-drivers/src/tests/testQueries.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,6 +1525,19 @@ export function testQueries(type: string, { includeIncrementalSchemaSuite, exten
15251525
expect(response.rawData()).toMatchSnapshot();
15261526
});
15271527

1528+
execute('querying BigECommerce: rolling window by 2 day without date range', async () => {
1529+
const response = await client.load({
1530+
measures: [
1531+
'BigECommerce.rollingCountBy2Day',
1532+
],
1533+
timeDimensions: [{
1534+
dimension: 'BigECommerce.orderDate',
1535+
granularity: 'month',
1536+
}],
1537+
});
1538+
expect(response.rawData()).toMatchSnapshot();
1539+
});
1540+
15281541
execute('querying BigECommerce: rolling window by 2 week', async () => {
15291542
const response = await client.load({
15301543
measures: [
@@ -1553,6 +1566,19 @@ export function testQueries(type: string, { includeIncrementalSchemaSuite, exten
15531566
expect(response.rawData()).toMatchSnapshot();
15541567
});
15551568

1569+
execute('querying BigECommerce: rolling window by 2 month without date range', async () => {
1570+
const response = await client.load({
1571+
measures: [
1572+
'BigECommerce.rollingCountBy2Month',
1573+
],
1574+
timeDimensions: [{
1575+
dimension: 'BigECommerce.orderDate',
1576+
granularity: 'month',
1577+
}],
1578+
});
1579+
expect(response.rawData()).toMatchSnapshot();
1580+
});
1581+
15561582
if (includeHLLSuite) {
15571583
execute('querying BigECommerce: rolling count_distinct_approx window by 2 day', async () => {
15581584
const response = await client.load({

packages/cubejs-testing-drivers/test/__snapshots__/bigquery-export-bucket-gcs-full.test.ts.snap

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6558,6 +6558,71 @@ Array [
65586558
]
65596559
`;
65606560

6561+
exports[`Queries with the @cubejs-backend/bigquery-driver querying BigECommerce: rolling window by 2 day without date range 1`] = `
6562+
Array [
6563+
Object {
6564+
"BigECommerce.orderDate": "2020-01-01T00:00:00.000",
6565+
"BigECommerce.orderDate.month": "2020-01-01T00:00:00.000",
6566+
"BigECommerce.rollingCountBy2Day": null,
6567+
},
6568+
Object {
6569+
"BigECommerce.orderDate": "2020-02-01T00:00:00.000",
6570+
"BigECommerce.orderDate.month": "2020-02-01T00:00:00.000",
6571+
"BigECommerce.rollingCountBy2Day": null,
6572+
},
6573+
Object {
6574+
"BigECommerce.orderDate": "2020-03-01T00:00:00.000",
6575+
"BigECommerce.orderDate.month": "2020-03-01T00:00:00.000",
6576+
"BigECommerce.rollingCountBy2Day": null,
6577+
},
6578+
Object {
6579+
"BigECommerce.orderDate": "2020-04-01T00:00:00.000",
6580+
"BigECommerce.orderDate.month": "2020-04-01T00:00:00.000",
6581+
"BigECommerce.rollingCountBy2Day": null,
6582+
},
6583+
Object {
6584+
"BigECommerce.orderDate": "2020-05-01T00:00:00.000",
6585+
"BigECommerce.orderDate.month": "2020-05-01T00:00:00.000",
6586+
"BigECommerce.rollingCountBy2Day": null,
6587+
},
6588+
Object {
6589+
"BigECommerce.orderDate": "2020-06-01T00:00:00.000",
6590+
"BigECommerce.orderDate.month": "2020-06-01T00:00:00.000",
6591+
"BigECommerce.rollingCountBy2Day": null,
6592+
},
6593+
Object {
6594+
"BigECommerce.orderDate": "2020-07-01T00:00:00.000",
6595+
"BigECommerce.orderDate.month": "2020-07-01T00:00:00.000",
6596+
"BigECommerce.rollingCountBy2Day": null,
6597+
},
6598+
Object {
6599+
"BigECommerce.orderDate": "2020-08-01T00:00:00.000",
6600+
"BigECommerce.orderDate.month": "2020-08-01T00:00:00.000",
6601+
"BigECommerce.rollingCountBy2Day": null,
6602+
},
6603+
Object {
6604+
"BigECommerce.orderDate": "2020-09-01T00:00:00.000",
6605+
"BigECommerce.orderDate.month": "2020-09-01T00:00:00.000",
6606+
"BigECommerce.rollingCountBy2Day": null,
6607+
},
6608+
Object {
6609+
"BigECommerce.orderDate": "2020-10-01T00:00:00.000",
6610+
"BigECommerce.orderDate.month": "2020-10-01T00:00:00.000",
6611+
"BigECommerce.rollingCountBy2Day": 1,
6612+
},
6613+
Object {
6614+
"BigECommerce.orderDate": "2020-11-01T00:00:00.000",
6615+
"BigECommerce.orderDate.month": "2020-11-01T00:00:00.000",
6616+
"BigECommerce.rollingCountBy2Day": null,
6617+
},
6618+
Object {
6619+
"BigECommerce.orderDate": "2020-12-01T00:00:00.000",
6620+
"BigECommerce.orderDate.month": "2020-12-01T00:00:00.000",
6621+
"BigECommerce.rollingCountBy2Day": null,
6622+
},
6623+
]
6624+
`;
6625+
65616626
exports[`Queries with the @cubejs-backend/bigquery-driver querying BigECommerce: rolling window by 2 month 1`] = `
65626627
Array [
65636628
Object {
@@ -6623,6 +6688,71 @@ Array [
66236688
]
66246689
`;
66256690

6691+
exports[`Queries with the @cubejs-backend/bigquery-driver querying BigECommerce: rolling window by 2 month without date range 1`] = `
6692+
Array [
6693+
Object {
6694+
"BigECommerce.orderDate": "2020-01-01T00:00:00.000",
6695+
"BigECommerce.orderDate.month": "2020-01-01T00:00:00.000",
6696+
"BigECommerce.rollingCountBy2Month": 2,
6697+
},
6698+
Object {
6699+
"BigECommerce.orderDate": "2020-02-01T00:00:00.000",
6700+
"BigECommerce.orderDate.month": "2020-02-01T00:00:00.000",
6701+
"BigECommerce.rollingCountBy2Month": 3,
6702+
},
6703+
Object {
6704+
"BigECommerce.orderDate": "2020-03-01T00:00:00.000",
6705+
"BigECommerce.orderDate.month": "2020-03-01T00:00:00.000",
6706+
"BigECommerce.rollingCountBy2Month": 3,
6707+
},
6708+
Object {
6709+
"BigECommerce.orderDate": "2020-04-01T00:00:00.000",
6710+
"BigECommerce.orderDate.month": "2020-04-01T00:00:00.000",
6711+
"BigECommerce.rollingCountBy2Month": 3,
6712+
},
6713+
Object {
6714+
"BigECommerce.orderDate": "2020-05-01T00:00:00.000",
6715+
"BigECommerce.orderDate.month": "2020-05-01T00:00:00.000",
6716+
"BigECommerce.rollingCountBy2Month": 6,
6717+
},
6718+
Object {
6719+
"BigECommerce.orderDate": "2020-06-01T00:00:00.000",
6720+
"BigECommerce.orderDate.month": "2020-06-01T00:00:00.000",
6721+
"BigECommerce.rollingCountBy2Month": 12,
6722+
},
6723+
Object {
6724+
"BigECommerce.orderDate": "2020-07-01T00:00:00.000",
6725+
"BigECommerce.orderDate.month": "2020-07-01T00:00:00.000",
6726+
"BigECommerce.rollingCountBy2Month": 7,
6727+
},
6728+
Object {
6729+
"BigECommerce.orderDate": "2020-08-01T00:00:00.000",
6730+
"BigECommerce.orderDate.month": "2020-08-01T00:00:00.000",
6731+
"BigECommerce.rollingCountBy2Month": null,
6732+
},
6733+
Object {
6734+
"BigECommerce.orderDate": "2020-09-01T00:00:00.000",
6735+
"BigECommerce.orderDate.month": "2020-09-01T00:00:00.000",
6736+
"BigECommerce.rollingCountBy2Month": 6,
6737+
},
6738+
Object {
6739+
"BigECommerce.orderDate": "2020-10-01T00:00:00.000",
6740+
"BigECommerce.orderDate.month": "2020-10-01T00:00:00.000",
6741+
"BigECommerce.rollingCountBy2Month": 10,
6742+
},
6743+
Object {
6744+
"BigECommerce.orderDate": "2020-11-01T00:00:00.000",
6745+
"BigECommerce.orderDate.month": "2020-11-01T00:00:00.000",
6746+
"BigECommerce.rollingCountBy2Month": 13,
6747+
},
6748+
Object {
6749+
"BigECommerce.orderDate": "2020-12-01T00:00:00.000",
6750+
"BigECommerce.orderDate.month": "2020-12-01T00:00:00.000",
6751+
"BigECommerce.rollingCountBy2Month": 16,
6752+
},
6753+
]
6754+
`;
6755+
66266756
exports[`Queries with the @cubejs-backend/bigquery-driver querying BigECommerce: rolling window by 2 week 1`] = `
66276757
Array [
66286758
Object {

0 commit comments

Comments
 (0)