Skip to content

Commit

Permalink
Merge branch 'master' into feature/clickhouse_utf8_filter_order
Browse files Browse the repository at this point in the history
  • Loading branch information
KSDaemon authored Feb 6, 2025
2 parents ce3ec56 + 7cf2287 commit ee06aee
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 6 deletions.
83 changes: 79 additions & 4 deletions packages/cubejs-dremio-driver/driver/DremioQuery.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { BaseFilter, BaseQuery } = require('@cubejs-backend/schema-compiler');
const { parseSqlInterval } = require('@cubejs-backend/shared');

const GRANULARITY_TO_INTERVAL = {
week: (date) => `DATE_TRUNC('week', ${date})`,
Expand Down Expand Up @@ -55,15 +56,39 @@ class DremioQuery extends BaseQuery {
}

dateTimeCast(value) {
return `TO_TIMESTAMP(${value})`;
return `TO_TIMESTAMP(${value}, 'YYYY-MM-DD"T"HH24:MI:SS.FFF')`;
}

subtractInterval(date, interval) {
return `DATE_SUB(${date}, INTERVAL ${interval})`;
const formattedTimeIntervals = this.formatInterval(interval);
const intervalFormatted = formattedTimeIntervals[0];
const timeUnit = formattedTimeIntervals[1];
return `DATE_SUB(${date}, CAST(${intervalFormatted} as INTERVAL ${timeUnit}))`;
}

addInterval(date, interval) {
return `DATE_ADD(${date}, INTERVAL ${interval})`;
const formattedTimeIntervals = this.formatInterval(interval);
const intervalFormatted = formattedTimeIntervals[0];
const timeUnit = formattedTimeIntervals[1];
return `DATE_ADD(${date}, CAST(${intervalFormatted} as INTERVAL ${timeUnit}))`;
}

/**
* @param {string} timestamp
* @param {string} interval
* @returns {string}
*/
addTimestampInterval(timestamp, interval) {
return this.addInterval(timestamp, interval);
}

/**
* @param {string} timestamp
* @param {string} interval
* @returns {string}
*/
subtractTimestampInterval(timestamp, interval) {
return this.subtractInterval(timestamp, interval);
}

timeGroupedColumn(granularity, dimension) {
Expand All @@ -78,7 +103,8 @@ class DremioQuery extends BaseQuery {
const values = timeDimension.timeSeries().map(
([from, to]) => `select '${from}' f, '${to}' t`
).join(' UNION ALL ');
return `SELECT TO_TIMESTAMP(dates.f, 'YYYY-MM-DDTHH:MI:SS.FFF') date_from, TO_TIMESTAMP(dates.t, 'YYYY-MM-DDTHH:MI:SS.FFF') date_to FROM (${values}) AS dates`;

return `SELECT TO_TIMESTAMP(dates.f, 'YYYY-MM-DD"T"HH24:MI:SS.FFF') date_from, TO_TIMESTAMP(dates.t, 'YYYY-MM-DD"T"HH24:MI:SS.FFF') date_to FROM (${values}) AS dates`;
}

concatStringsSql(strings) {
Expand All @@ -92,6 +118,55 @@ class DremioQuery extends BaseQuery {
wrapSegmentForDimensionSelect(sql) {
return `IF(${sql}, 1, 0)`;
}

/**
* The input interval with (possible) plural units, like "1 hour 2 minutes", "2 year", "3 months", "4 weeks", "5 days", "3 months 24 days 15 minutes", ...
* will be converted to Dremio dialect.
* @see https://docs.dremio.com/24.3.x/reference/sql/sql-functions/functions/DATE_ADD/
* @see https://docs.dremio.com/24.3.x/reference/sql/sql-functions/functions/DATE_SUB/
* It returns a tuple of (formatted interval, timeUnit to use in date functions)
* This function only supports the following scenarios for now:
* ie. n year[s] or n quarter[s] or n month[s] or n week[s] or n day[s]
*/
formatInterval(interval) {
const intervalParsed = parseSqlInterval(interval);
const intKeys = Object.keys(intervalParsed).length;

if (intervalParsed.year && intKeys === 1) {
return [`${intervalParsed.year}`, 'YEAR'];
} else if (intervalParsed.quarter && intKeys === 1) {
// dremio interval does not support quarter. Convert to month
return [`${intervalParsed.quarter * 3}`, 'MONTH'];
} else if (intervalParsed.week && intKeys === 1) {
// dremio interval does not support week. Convert to days
return [`${intervalParsed.week * 7}`, 'DAY'];
} else if (intervalParsed.month && intKeys === 1) {
return [`${intervalParsed.month}`, 'MONTH'];
} else if (intervalParsed.month && intKeys === 1) {
return [`${intervalParsed.day}`, 'DAY'];
} else if (intervalParsed.hour && intKeys === 1) {
return [`${intervalParsed.hour}`, 'HOUR'];
} else if (intervalParsed.minute && intKeys === 1) {
return [`${intervalParsed.minute}`, 'MINUTE'];
} else if (intervalParsed.second && intKeys === 1) {
return [`${intervalParsed.second}`, 'SECOND'];
}

throw new Error(`Cannot transform interval expression "${interval}" to Dremio dialect`);
}

sqlTemplates() {
const templates = super.sqlTemplates();
templates.functions.CURRENTDATE = 'CURRENT_DATE';
templates.functions.DATETRUNC = 'DATE_TRUNC(\'{{ date_part }}\', {{ args_concat }})';
templates.functions.DATEPART = 'DATE_PART(\'{{ date_part }}\', {{ args_concat }})';
// really need the date locale formatting here...
templates.functions.DATE = 'TO_DATE({{ args_concat }},\'YYYY-MM-DD\', 1)';
templates.functions.DATEDIFF = 'DATE_DIFF(DATE, DATE_TRUNC(\'{{ date_part }}\', {{ args[1] }}), DATE_TRUNC(\'{{ date_part }}\', {{ args[2] }}))';
templates.expressions.interval_single_date_part = 'CAST({{ num }} as INTERVAL {{ date_part }})';
templates.quotes.identifiers = '"';
return templates;
}
}

module.exports = DremioQuery;
4 changes: 2 additions & 2 deletions rust/cubestore/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"author": "Cube Dev, Inc.",
"license": "Apache-2.0",
"devDependencies": {
"@cubejs-backend/linter": "1.2.0",
"@cubejs-backend/linter": "1.2.1",
"@types/jest": "^27",
"@types/node": "^12",
"jest": "^27",
Expand All @@ -37,7 +37,7 @@
"access": "public"
},
"dependencies": {
"@cubejs-backend/shared": "1.2.0",
"@cubejs-backend/shared": "1.2.1",
"@octokit/core": "^3.2.5",
"source-map-support": "^0.5.19"
},
Expand Down

0 comments on commit ee06aee

Please sign in to comment.