Skip to content
Merged
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

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions packages/cubejs-schema-compiler/test/unit/oracle-query.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,9 @@ describe('OracleQuery', () => {
expect(sql).not.toMatch(/\bas\s+q_\d+/);

// Should have q_0 alias (with space around it, indicating no AS).
// The native planner quotes the alias ("q_0").
expect(sql).toMatch(/\)\s+"?q_0"?/);
// The native planner quotes the alias ("q_0") and may reference the
// source as a bare CTE name after trivial-subquery collapse.
expect(sql).toMatch(/[)\w]\s+"?q_0"?/);
});

it('does not use AS keyword with multiple rolling window measures (YoY scenario)', async () => {
Expand Down Expand Up @@ -191,7 +192,7 @@ describe('OracleQuery', () => {
expect(sql).not.toMatch(/\bas\s+q_\d+/);

// Verify pattern is ) q_X not ) AS q_X (the native planner quotes the alias)
expect(sql).toMatch(/\)\s+"?q_\d+"?/);
expect(sql).toMatch(/[)\w]\s+"?q_\d+"?/);
});

it('does not use AS keyword in INNER JOIN subqueries', async () => {
Expand Down Expand Up @@ -280,8 +281,8 @@ describe('OracleQuery', () => {

// Should have multiple subquery aliases without AS (the native planner
// quotes the aliases and joins subqueries explicitly rather than with commas).
expect(sql).toMatch(/\)\s+"?q_0"?/);
expect(sql).toMatch(/\)\s+"?q_1"?/);
expect(sql).toMatch(/[)\w]\s+"?q_0"?/);
expect(sql).toMatch(/[)\w]\s+"?q_1"?/);

// Should NOT have AS before q_ aliases
expect(sql).not.toMatch(/\bAS\s+q_\d+/i);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
orchestratorOptions: {
preAggregationsOptions: {
externalRefresh: false,
},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
views:
- name: performance_view
cubes:
- join_path: sales
includes:
- account
- product
- date
- total
- rolling_amount
- rolling_amount_change
- rolling_amount_growth_pct

- join_path: share_metrics
includes:
- rolling_share_change
- name: date
alias: ms_date

- join_path: rolling_window_dim
includes:
- rolling_window
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Shared rolling-window selector (calc group): a single-row cube hosting a
# `type: switch` dimension that case entrypoint measures in several fact
# cubes dispatch on, so one filter resolves the window for all of them.
cubes:
- name: rolling_window_dim
sql: SELECT 1 AS one
public: false
dimensions:
- name: one
sql: one
type: number
primary_key: true
public: false

- name: rolling_window
type: switch
values:
- R3
- YTD
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
cubes:
- name: sales
sql: >
SELECT 'A1' AS account, 'P1' AS product, '2017-01-15T00:00:00.000Z'::timestamptz AS sale_date, 10.0 AS amount UNION ALL
SELECT 'A1' AS account, 'P1' AS product, '2017-02-15T00:00:00.000Z'::timestamptz AS sale_date, 20.0 AS amount UNION ALL
SELECT 'A1' AS account, 'P1' AS product, '2017-03-15T00:00:00.000Z'::timestamptz AS sale_date, 30.0 AS amount UNION ALL
SELECT 'A1' AS account, 'P1' AS product, '2017-04-15T00:00:00.000Z'::timestamptz AS sale_date, 40.0 AS amount UNION ALL
SELECT 'A1' AS account, 'P1' AS product, '2017-05-15T00:00:00.000Z'::timestamptz AS sale_date, 50.0 AS amount UNION ALL
SELECT 'A1' AS account, 'P1' AS product, '2017-06-15T00:00:00.000Z'::timestamptz AS sale_date, 60.0 AS amount UNION ALL
SELECT 'A1' AS account, 'P2' AS product, '2017-01-15T00:00:00.000Z'::timestamptz AS sale_date, 5.0 AS amount UNION ALL
SELECT 'A1' AS account, 'P2' AS product, '2017-02-15T00:00:00.000Z'::timestamptz AS sale_date, 5.0 AS amount UNION ALL
SELECT 'A1' AS account, 'P2' AS product, '2017-03-15T00:00:00.000Z'::timestamptz AS sale_date, 5.0 AS amount UNION ALL
SELECT 'A1' AS account, 'P2' AS product, '2017-04-15T00:00:00.000Z'::timestamptz AS sale_date, 5.0 AS amount UNION ALL
SELECT 'A1' AS account, 'P2' AS product, '2017-05-15T00:00:00.000Z'::timestamptz AS sale_date, 5.0 AS amount UNION ALL
SELECT 'A1' AS account, 'P2' AS product, '2017-06-15T00:00:00.000Z'::timestamptz AS sale_date, 5.0 AS amount UNION ALL
SELECT 'A2' AS account, 'P1' AS product, '2017-01-15T00:00:00.000Z'::timestamptz AS sale_date, 1.0 AS amount UNION ALL
SELECT 'A2' AS account, 'P1' AS product, '2017-02-15T00:00:00.000Z'::timestamptz AS sale_date, 1.0 AS amount UNION ALL
SELECT 'A2' AS account, 'P1' AS product, '2017-03-15T00:00:00.000Z'::timestamptz AS sale_date, 1.0 AS amount UNION ALL
SELECT 'A2' AS account, 'P1' AS product, '2017-04-15T00:00:00.000Z'::timestamptz AS sale_date, 1.0 AS amount UNION ALL
SELECT 'A2' AS account, 'P1' AS product, '2017-05-15T00:00:00.000Z'::timestamptz AS sale_date, 1.0 AS amount UNION ALL
SELECT 'A2' AS account, 'P1' AS product, '2017-06-15T00:00:00.000Z'::timestamptz AS sale_date, 1.0 AS amount
public: false

joins:
# Virtual edge to the shared rolling-window calc group cube (single
# row, 1 = 1) so the join graph connects; the switch dimension itself
# is cross-joined as a virtual values table, not via this SQL.
- name: rolling_window_dim
sql: "1 = 1"
relationship: many_to_one

dimensions:
- name: id
sql: "{CUBE}.account || '|' || {CUBE}.product || '|' || CAST({CUBE}.sale_date AS TEXT)"
type: string
primary_key: true
public: false

- name: account
sql: account
type: string

- name: product
sql: product
type: string

- name: date
sql: sale_date
type: time

measures:
- name: total
sql: amount
type: sum

- name: r3_amount
sql: amount
type: sum
public: false
rolling_window:
trailing: 3 month

- name: prev_r3_amount
multi_stage: true
sql: "{r3_amount}"
type: number
public: false
time_shift:
- interval: 3 month
type: prior

- name: r3_amount_change
multi_stage: true
type: number
public: false
sql: "({r3_amount} - {prev_r3_amount})"

- name: ytd_amount
sql: amount
type: sum
public: false
rolling_window:
type: to_date
granularity: year

- name: prev_ytd_amount
multi_stage: true
sql: "{ytd_amount}"
type: number
public: false
time_shift:
- interval: 1 year
type: prior

- name: ytd_amount_change
multi_stage: true
type: number
public: false
sql: "({ytd_amount} - {prev_ytd_amount})"

- name: r3_amount_growth_pct
multi_stage: true
type: number
public: false
format: percent
sql: >
CASE
WHEN {r3_amount} IS NULL OR {prev_r3_amount} IS NULL OR {prev_r3_amount} = 0
THEN NULL
ELSE ({r3_amount} - {prev_r3_amount}) / {prev_r3_amount}
END

- name: ytd_amount_growth_pct
multi_stage: true
type: number
public: false
format: percent
sql: >
CASE
WHEN {ytd_amount} IS NULL OR {prev_ytd_amount} IS NULL OR {prev_ytd_amount} = 0
THEN NULL
ELSE ({ytd_amount} - {prev_ytd_amount}) / {prev_ytd_amount}
END

- name: rolling_amount
multi_stage: true
type: number
case:
switch: "{rolling_window_dim.rolling_window}"
when:
- value: R3
sql: "{CUBE.r3_amount}"
else:
sql: "{CUBE.ytd_amount}"

- name: rolling_amount_change
multi_stage: true
type: number
case:
switch: "{rolling_window_dim.rolling_window}"
when:
- value: R3
sql: "{CUBE.r3_amount_change}"
else:
sql: "{CUBE.ytd_amount_change}"

- name: rolling_amount_growth_pct
multi_stage: true
type: number
format: percent
case:
switch: "{rolling_window_dim.rolling_window}"
when:
- value: R3
sql: "{CUBE.r3_amount_growth_pct}"
else:
sql: "{CUBE.ytd_amount_growth_pct}"

pre_aggregations:
- name: perf_rolling
measures:
- total
- r3_amount
- ytd_amount
# The rolling_window calc group is virtual and resolved at query
# time, so it is intentionally NOT stored in the rollup.
dimensions:
- account
- product
time_dimension: date
granularity: month
allow_non_strict_date_range_match: true
scheduled_refresh: false
refresh_key:
every: 1 hour
Loading
Loading