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
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
cubes:
- name: regions
sql: "SELECT * FROM regions"
dimensions:
- name: id
type: number
sql: id
primary_key: true
- name: name
type: string
sql: name

- name: customers
sql: "SELECT * FROM customers"
joins:
Expand All @@ -11,6 +22,9 @@ cubes:
- name: reviews
relationship: one_to_many
sql: "{customers}.id = {reviews.customer_id}"
- name: regions
relationship: many_to_one
sql: "{customers}.region_id = {regions.id}"
dimensions:
- name: id
type: number
Expand All @@ -28,6 +42,14 @@ cubes:
measures:
- name: count
type: count
- name: total_lifetime_value
type: sum
sql: lifetime_value
- name: total_lifetime_value_for_east
type: sum
sql: lifetime_value
filters:
- sql: "{regions.name} = 'East'"

- name: orders
sql: "SELECT * FROM orders"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ cubes:
measures:
- name: count
type: count
- name: total_lifetime_value
type: sum
sql: lifetime_value

- name: payments
sql: "SELECT * FROM mf_payments"
Expand All @@ -39,6 +42,9 @@ cubes:
- name: amount
type: number
sql: amount
- name: payment_type
type: string
sql: payment_type
- name: created_at
type: time
sql: created_at
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,19 @@ DROP TABLE IF EXISTS reviews CASCADE;
DROP TABLE IF EXISTS returns CASCADE;
DROP TABLE IF EXISTS orders CASCADE;
DROP TABLE IF EXISTS customers CASCADE;
DROP TABLE IF EXISTS regions CASCADE;

CREATE TABLE regions (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);

CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
city TEXT NOT NULL,
region_id INTEGER NOT NULL REFERENCES regions(id),
lifetime_value NUMERIC(10, 2) NOT NULL,
created_at TIMESTAMP NOT NULL
);

Expand All @@ -33,11 +41,15 @@ CREATE TABLE reviews (
created_at TIMESTAMP NOT NULL
);

INSERT INTO customers (id, name, city, created_at) VALUES
(1, 'Alice', 'New York', '2025-01-15 10:00:00'),
(2, 'Bob', 'Boston', '2025-02-01 12:00:00'),
(3, 'Charlie', 'Chicago', '2025-02-15 09:00:00'),
(4, 'Diana', 'New York', '2025-03-01 08:00:00');
INSERT INTO regions (id, name) VALUES
(1, 'East'),
(2, 'Midwest');

INSERT INTO customers (id, name, city, region_id, lifetime_value, created_at) VALUES
(1, 'Alice', 'New York', 1, 1000.00, '2025-01-15 10:00:00'),
(2, 'Bob', 'Boston', 1, 2000.00, '2025-02-01 12:00:00'),
(3, 'Charlie', 'Chicago', 2, 500.00, '2025-02-15 09:00:00'),
(4, 'Diana', 'New York', 1, 1500.00, '2025-03-01 08:00:00');

INSERT INTO orders (id, customer_id, status, amount, created_at) VALUES
(1, 1, 'completed', 100.00, '2025-03-01 10:00:00'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ CREATE TABLE mf_customers (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
city TEXT,
lifetime_value NUMERIC(10, 2) NOT NULL,
registered_at TIMESTAMP NOT NULL
);

CREATE TABLE mf_payments (
id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL REFERENCES mf_customers(id),
amount NUMERIC(10, 2) NOT NULL,
payment_type TEXT NOT NULL,
created_at TIMESTAMP NOT NULL
);

Expand All @@ -23,19 +25,19 @@ CREATE TABLE mf_messages (
);

-- Customers registered on different days in January 2024
INSERT INTO mf_customers (id, name, city, registered_at) VALUES
(1, 'Alice', 'New York', '2024-01-10 10:00:00'),
(2, 'Bob', 'San Francisco', '2024-01-15 12:00:00'),
(3, 'Charlie', 'Boston', '2024-01-20 09:00:00');
INSERT INTO mf_customers (id, name, city, lifetime_value, registered_at) VALUES
(1, 'Alice', 'New York', 500.00, '2024-01-10 10:00:00'),
(2, 'Bob', 'San Francisco', 300.00, '2024-01-15 12:00:00'),
(3, 'Charlie', 'Boston', 200.00, '2024-01-20 09:00:00');

-- Payments: each customer pays at various times after registration
INSERT INTO mf_payments (id, customer_id, amount, created_at) VALUES
(1, 1, 100.00, '2024-01-11 10:00:00'),
(2, 1, 200.00, '2024-01-18 14:00:00'),
(3, 2, 150.00, '2024-01-16 11:00:00'),
(4, 2, 50.00, '2024-01-22 09:00:00'),
(5, 3, 75.00, '2024-01-21 16:00:00'),
(6, 3, 125.00, '2024-01-24 10:00:00');
INSERT INTO mf_payments (id, customer_id, amount, payment_type, created_at) VALUES
(1, 1, 100.00, 'card', '2024-01-11 10:00:00'),
(2, 1, 200.00, 'cash', '2024-01-18 14:00:00'),
(3, 2, 150.00, 'card', '2024-01-16 11:00:00'),
(4, 2, 50.00, 'card', '2024-01-22 09:00:00'),
(5, 3, 75.00, 'cash', '2024-01-21 16:00:00'),
(6, 3, 125.00, 'card', '2024-01-24 10:00:00');

-- Messages: support messages from each customer
INSERT INTO mf_messages (id, customer_id, created_at) VALUES
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,45 @@ async fn test_multiplied_with_join_filter_segment_time() {
}
}

// 10.2b: Same as 10.2 but with SUM hub measure → AggregateMultipliedSubquery
// instead of count (which just becomes count distinct)
#[tokio::test(flavor = "multi_thread")]
async fn test_multiplied_aggregate_with_join_filter_segment_time() {
let ctx = create_multi_fact_context();

let query = indoc! {"
measures:
- customers.total_lifetime_value
- orders.count
dimensions:
- customers.name
segments:
- orders.completed_orders
filters:
- dimension: customers.city
operator: equals
values:
- New York
time_dimensions:
- dimension: orders.created_at
granularity: month
dateRange:
- \"2025-03-01\"
- \"2025-03-31\"
order:
- id: customers.name
"};

ctx.build_sql(query).unwrap();

if let Some(result) = ctx
.try_execute_pg(query, "integration_multi_fact_tables.sql")
.await
{
insta::assert_snapshot!(result);
}
}

// 10.3: Subquery dimension filter + time dateRange
#[tokio::test(flavor = "multi_thread")]
async fn test_subquery_dim_filter_with_time_range() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,54 @@ async fn test_multiplied_with_order_and_limit() {
}
}

#[tokio::test(flavor = "multi_thread")]
async fn test_multiplied_aggregate_hub_sum_measure() {
let ctx = create_context();

// customers.total_lifetime_value (SUM) by orders.status
// customers is multiplied in customers→orders join (one_to_many)
// SUM is not additive in multiplied context → AggregateMultipliedSubquery
// Measure references only customers → source = Cube (no MeasureSubquery)
let query = indoc! {"
measures:
- customers.total_lifetime_value
dimensions:
- orders.status
order:
- id: orders.status
"};

ctx.build_sql(query).unwrap();

if let Some(result) = ctx.try_execute_pg(query, SEED).await {
insta::assert_snapshot!(result);
}
}

#[tokio::test(flavor = "multi_thread")]
async fn test_multiplied_aggregate_with_measure_subquery() {
let ctx = create_context();

// customers.total_lifetime_value_for_east (SUM with filter {regions.name} = 'East')
// customers is multiplied in customers→orders join → AggregateMultipliedSubquery
// Measure filter references regions cube → MeasureSubquery (customers→regions join,
// where customers is NOT multiplied since many_to_one)
let query = indoc! {"
measures:
- customers.total_lifetime_value_for_east
dimensions:
- orders.status
order:
- id: orders.status
"};

ctx.build_sql(query).unwrap();

if let Some(result) = ctx.try_execute_pg(query, SEED).await {
insta::assert_snapshot!(result);
}
}

#[tokio::test(flavor = "multi_thread")]
async fn test_non_multiplied_multi_join() {
let ctx = create_context();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,37 @@ async fn test_two_rolling_aggregated_by_day() {
}
}

#[tokio::test(flavor = "multi_thread")]
async fn test_rolling_with_multiplied_aggregate_hub_measure() {
let ctx = create_context();

// Combines multi-stage (rolling_sum_7d) with AggregateMultipliedSubquery
// (customers.total_lifetime_value SUM on hub, multiplied by payments).
// payments.payment_type dimension forces customers→payments join,
// making customers multiplied → AggregateMultipliedSubquery for the SUM measure.
let query = indoc! {r#"
measures:
- payments.rolling_sum_7d
- customers.total_lifetime_value
dimensions:
- payments.payment_type
time_dimensions:
- dimension: customers.registered_at
granularity: day
dateRange:
- "2024-01-10"
- "2024-01-25"
order:
- id: payments.payment_type
"#};

ctx.build_sql(query).unwrap();

if let Some(result) = ctx.try_execute_pg(query, SEED).await {
insta::assert_snapshot!(result);
}
}

#[tokio::test(flavor = "multi_thread")]
async fn test_two_rolling_with_shared_dimension_and_filter() {
let ctx = create_context();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
source: cubesqlplanner/src/tests/integration/rolling_window/multi_fact.rs
expression: result
---
payments__payment_type | customers__registered_at_day | payments__rolling_sum_7d | customers__total_lifetime_value
-----------------------+------------------------------+--------------------------+--------------------------------
card | 2024-01-10 00:00:00 | 100.00 | 500.00
card | 2024-01-11 00:00:00 | 100.00 | NULL
card | 2024-01-12 00:00:00 | 100.00 | NULL
card | 2024-01-13 00:00:00 | 100.00 | NULL
card | 2024-01-14 00:00:00 | 100.00 | NULL
card | 2024-01-15 00:00:00 | 300.00 | 300.00
card | 2024-01-16 00:00:00 | 300.00 | NULL
card | 2024-01-17 00:00:00 | 200.00 | NULL
card | 2024-01-18 00:00:00 | 200.00 | NULL
card | 2024-01-19 00:00:00 | 200.00 | NULL
card | 2024-01-20 00:00:00 | 325.00 | 200.00
card | 2024-01-21 00:00:00 | 325.00 | NULL
card | 2024-01-22 00:00:00 | 125.00 | NULL
card | 2024-01-23 00:00:00 | 125.00 | NULL
card | 2024-01-24 00:00:00 | 125.00 | NULL
card | 2024-01-25 00:00:00 | 125.00 | NULL
cash | 2024-01-10 00:00:00 | 200.00 | 500.00
cash | 2024-01-11 00:00:00 | 200.00 | NULL
cash | 2024-01-12 00:00:00 | 200.00 | NULL
cash | 2024-01-13 00:00:00 | 200.00 | NULL
cash | 2024-01-14 00:00:00 | 200.00 | NULL
cash | 2024-01-15 00:00:00 | 200.00 | NULL
cash | 2024-01-16 00:00:00 | 200.00 | NULL
cash | 2024-01-20 00:00:00 | 75.00 | 200.00
cash | 2024-01-21 00:00:00 | 75.00 | NULL
cash | 2024-01-22 00:00:00 | 75.00 | NULL
cash | 2024-01-23 00:00:00 | 75.00 | NULL
cash | 2024-01-24 00:00:00 | 75.00 | NULL
cash | 2024-01-25 00:00:00 | 75.00 | NULL
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
source: cubesqlplanner/src/tests/integration/combinations.rs
expression: result
---
customers__name | orders__created_at_month | customers__total_lifetime_value | orders__count
----------------+--------------------------+---------------------------------+--------------
Alice | 2025-03-01 00:00:00 | 1000.00 | 2
Diana | 2025-03-01 00:00:00 | 1500.00 | 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
source: cubesqlplanner/src/tests/integration/multi_fact.rs
expression: result
---
orders__status | customers__total_lifetime_value
---------------+--------------------------------
completed | 4500.00
pending | 3000.00
NULL | 500.00
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
source: cubesqlplanner/src/tests/integration/multi_fact.rs
expression: result
---
orders__status | customers__total_lifetime_value_for_east
---------------+-----------------------------------------
completed | 4500.00
pending | 3000.00
NULL | NULL
Loading