Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions packages/cubejs-schema-compiler/src/adapter/BaseQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -1380,8 +1380,8 @@ export class BaseQuery {
const join = R.drop(1, toJoin)
.map(
(q, i) => (this.dimensionAliasNames().length ?
`INNER JOIN ${this.wrapInParenthesis((q))} as q_${i + 1} ON ${this.dimensionsJoinCondition(`q_${i}`, `q_${i + 1}`)}` :
`, ${this.wrapInParenthesis(q)} as q_${i + 1}`),
`INNER JOIN ${this.wrapInParenthesis((q))} ${this.asSyntaxJoin} q_${i + 1} ON ${this.dimensionsJoinCondition(`q_${i}`, `q_${i + 1}`)}` :
`, ${this.wrapInParenthesis(q)} ${this.asSyntaxJoin} q_${i + 1}`),
).join('\n');

const columnsToSelect = this.evaluateSymbolSqlWithContext(
Expand Down Expand Up @@ -1410,7 +1410,7 @@ export class BaseQuery {
return `${toJoin[0].replace(/^SELECT/, `SELECT ${this.topLimit()}`)} ${this.orderBy()}${this.groupByDimensionLimit()}`;
}

return `SELECT ${this.topLimit()}${columnsToSelect} FROM ${this.wrapInParenthesis(toJoin[0])} as q_0 ${join}${havingFilters}${this.orderBy()}${this.groupByDimensionLimit()}`;
return `SELECT ${this.topLimit()}${columnsToSelect} FROM ${this.wrapInParenthesis(toJoin[0])} ${this.asSyntaxJoin} q_0 ${join}${havingFilters}${this.orderBy()}${this.groupByDimensionLimit()}`;
}

wrapInParenthesis(select) {
Expand Down Expand Up @@ -3857,6 +3857,11 @@ export class BaseQuery {
* @return {string}
*/
dimensionTimeGroupedColumn(dimension, granularity) {
// Handle case when granularity is not specified (e.g., time dimension used only for filtering)
if (!granularity) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you show the example when this function is called without granularity object?

return this.timeGroupedColumn(null, dimension);
}

let dtDate;

// Interval is aligned with natural calendar, so we can use DATE_TRUNC
Expand Down
85 changes: 84 additions & 1 deletion packages/cubejs-schema-compiler/src/adapter/OracleQuery.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { parseSqlInterval } from '@cubejs-backend/shared';
import { BaseQuery } from './BaseQuery';
import { BaseFilter } from './BaseFilter';
import { UserError } from '../compiler/UserError';
import { BaseDimension } from './BaseDimension';
import type { BaseDimension } from './BaseDimension';

const GRANULARITY_VALUE = {
day: 'DD',
Expand Down Expand Up @@ -89,6 +90,88 @@ export class OracleQuery extends BaseQuery {
return `TRUNC(${dimension}, '${GRANULARITY_VALUE[granularity]}')`;
}

/**
* Oracle uses ADD_MONTHS for year/month/quarter intervals
* and NUMTODSINTERVAL for day/hour/minute/second intervals
*/
public addInterval(date: string, interval: string): string {
const intervalParsed = parseSqlInterval(interval);
let res = date;

// Handle year/month/quarter using ADD_MONTHS
let totalMonths = 0;
if (intervalParsed.year) {
totalMonths += intervalParsed.year * 12;
}
if (intervalParsed.quarter) {
totalMonths += intervalParsed.quarter * 3;
}
if (intervalParsed.month) {
totalMonths += intervalParsed.month;
}

if (totalMonths !== 0) {
res = `ADD_MONTHS(${res}, ${totalMonths})`;
}

// Handle day/hour/minute/second using NUMTODSINTERVAL
if (intervalParsed.day) {
res = `${res} + NUMTODSINTERVAL(${intervalParsed.day}, 'DAY')`;
}
if (intervalParsed.hour) {
res = `${res} + NUMTODSINTERVAL(${intervalParsed.hour}, 'HOUR')`;
}
if (intervalParsed.minute) {
res = `${res} + NUMTODSINTERVAL(${intervalParsed.minute}, 'MINUTE')`;
}
if (intervalParsed.second) {
res = `${res} + NUMTODSINTERVAL(${intervalParsed.second}, 'SECOND')`;
}

return res;
}

/**
* Oracle subtraction uses ADD_MONTHS with negative values
* and subtracts NUMTODSINTERVAL for time units
*/
public subtractInterval(date: string, interval: string): string {
const intervalParsed = parseSqlInterval(interval);
let res = date;

// Handle year/month/quarter using ADD_MONTHS with negative values
let totalMonths = 0;
if (intervalParsed.year) {
totalMonths += intervalParsed.year * 12;
}
if (intervalParsed.quarter) {
totalMonths += intervalParsed.quarter * 3;
}
if (intervalParsed.month) {
totalMonths += intervalParsed.month;
}

if (totalMonths !== 0) {
res = `ADD_MONTHS(${res}, -${totalMonths})`;
}

// Handle day/hour/minute/second using NUMTODSINTERVAL with subtraction
if (intervalParsed.day) {
res = `${res} - NUMTODSINTERVAL(${intervalParsed.day}, 'DAY')`;
}
if (intervalParsed.hour) {
res = `${res} - NUMTODSINTERVAL(${intervalParsed.hour}, 'HOUR')`;
}
if (intervalParsed.minute) {
res = `${res} - NUMTODSINTERVAL(${intervalParsed.minute}, 'MINUTE')`;
}
if (intervalParsed.second) {
res = `${res} - NUMTODSINTERVAL(${intervalParsed.second}, 'SECOND')`;
}

return res;
}

public newFilter(filter) {
return new OracleFilter(this, filter);
}
Expand Down
Loading
Loading