Skip to content

Commit f910523

Browse files
committed
[WIP] Fixes for merge filter rule
Some queries in tests reduced to a single CubeScan with member expressions, so tests have changed
1 parent 0b532a1 commit f910523

File tree

3 files changed

+255
-100
lines changed

3 files changed

+255
-100
lines changed

rust/cubesql/cubesql/src/compile/mod.rs

Lines changed: 173 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -7242,49 +7242,88 @@ ORDER BY
72427242
displayable(physical_plan.as_ref()).indent()
72437243
);
72447244

7245+
fn trivial_member_expr(cube: &str, member: &str, alias: &str) -> String {
7246+
json!({
7247+
"cube_name": cube,
7248+
"alias": alias,
7249+
"cube_params": [cube],
7250+
"expr": format!("${{{cube}.{member}}}"),
7251+
"grouping_set": null,
7252+
})
7253+
.to_string()
7254+
}
7255+
72457256
assert_eq!(
7246-
query_plan.as_logical_plan().find_cube_scan().request,
7257+
query_plan
7258+
.as_logical_plan()
7259+
.find_cube_scan_wrapper()
7260+
.request
7261+
.unwrap(),
72477262
V1LoadRequestQuery {
72487263
measures: Some(vec![
7249-
"WideCube.measure1".to_string(),
7250-
"WideCube.measure2".to_string(),
7251-
"WideCube.measure3".to_string(),
7252-
"WideCube.measure4".to_string(),
7264+
json!({
7265+
"cube_name": "WideCube",
7266+
"alias": "max_source_measu",
7267+
"cube_params": ["WideCube"],
7268+
"expr": "MAX(${WideCube.measure1})",
7269+
"grouping_set": null,
7270+
})
7271+
.to_string(),
7272+
json!({
7273+
"cube_name": "WideCube",
7274+
"alias": "max_source_measu_1",
7275+
"cube_params": ["WideCube"],
7276+
"expr": "MAX(${WideCube.measure2})",
7277+
"grouping_set": null,
7278+
})
7279+
.to_string(),
7280+
json!({
7281+
"cube_name": "WideCube",
7282+
"alias": "sum_source_measu",
7283+
"cube_params": ["WideCube"],
7284+
"expr": "SUM(${WideCube.measure3})",
7285+
"grouping_set": null,
7286+
})
7287+
.to_string(),
7288+
json!({
7289+
"cube_name": "WideCube",
7290+
"alias": "max_source_measu_2",
7291+
"cube_params": ["WideCube"],
7292+
"expr": "MAX(${WideCube.measure4})",
7293+
"grouping_set": null,
7294+
})
7295+
.to_string(),
72537296
]),
72547297
dimensions: Some(vec![
7255-
"WideCube.dim1".to_string(),
7256-
"WideCube.dim2".to_string(),
7257-
"WideCube.dim3".to_string(),
7258-
"WideCube.dim4".to_string(),
7298+
trivial_member_expr("WideCube", "dim2", "source_dim2"),
7299+
trivial_member_expr("WideCube", "dim3", "source_dim3"),
7300+
trivial_member_expr("WideCube", "dim4", "source_dim4"),
7301+
json!({
7302+
"cube_name": "WideCube",
7303+
"alias": "source_pivot_gro",
7304+
"cube_params": ["WideCube"],
7305+
"expr": "0",
7306+
"grouping_set": null,
7307+
})
7308+
.to_string()
7309+
]),
7310+
segments: Some(vec![json!({
7311+
"cube_name": "WideCube",
7312+
"alias": "widecube_dim1___",
7313+
"cube_params": ["WideCube"],
7314+
"expr": "(${WideCube.dim1} = $0$)",
7315+
"grouping_set": null,
7316+
})
7317+
.to_string()]),
7318+
order: Some(vec![
7319+
vec!["source_dim2".to_string(), "asc".to_string(),],
7320+
vec!["source_dim3".to_string(), "asc".to_string(),],
7321+
vec!["source_dim4".to_string(), "asc".to_string(),],
7322+
vec!["source_pivot_gro".to_string(), "asc".to_string(),],
72597323
]),
7260-
segments: Some(vec![]),
7261-
order: Some(vec![]),
7262-
filters: Some(vec![V1LoadRequestQueryFilterItem {
7263-
member: Some("WideCube.dim1".to_string()),
7264-
operator: Some("equals".to_string()),
7265-
values: Some(vec!["foo".to_string()]),
7266-
or: None,
7267-
and: None,
7268-
}]),
7269-
ungrouped: Some(true),
72707324
..Default::default()
72717325
}
72727326
);
7273-
assert!(!query_plan
7274-
.as_logical_plan()
7275-
.find_cube_scan_wrapper()
7276-
.wrapped_sql
7277-
.unwrap()
7278-
.sql
7279-
.contains("ungrouped"));
7280-
7281-
assert!(query_plan
7282-
.as_logical_plan()
7283-
.find_cube_scan_wrapper()
7284-
.wrapped_sql
7285-
.unwrap()
7286-
.sql
7287-
.contains("[\"dim2\",\"asc\"]"));
72887327
}
72897328

72907329
#[tokio::test]
@@ -11609,15 +11648,39 @@ ORDER BY "source"."str0" ASC
1160911648
.await
1161011649
.as_logical_plan();
1161111650

11612-
let sql = logical_plan
11613-
.find_cube_scan_wrapper()
11614-
.wrapped_sql
11615-
.unwrap()
11616-
.sql;
11617-
11618-
assert!(sql.contains("LOWER("));
11619-
assert!(sql.contains("GROUP BY "));
11620-
assert!(sql.contains("ORDER BY "));
11651+
assert_eq!(
11652+
logical_plan
11653+
.find_cube_scan_wrapper()
11654+
.request
11655+
.unwrap(),
11656+
V1LoadRequestQuery {
11657+
measures: Some(vec![]),
11658+
dimensions: Some(vec![
11659+
json!({
11660+
"cube_name": "KibanaSampleDataEcommerce",
11661+
"alias": "ta_1_order_date_",
11662+
"cube_params": ["KibanaSampleDataEcommerce", "Logs"],
11663+
"expr": "((${KibanaSampleDataEcommerce.order_date} = DATE('1994-05-01')) OR (${KibanaSampleDataEcommerce.order_date} = DATE('1996-05-03')))",
11664+
"grouping_set": null,
11665+
}).to_string(),
11666+
]),
11667+
segments: Some(vec![
11668+
json!({
11669+
"cube_name": "KibanaSampleDataEcommerce",
11670+
"alias": "lower_ta_2_conte",
11671+
"cube_params": ["KibanaSampleDataEcommerce", "Logs"],
11672+
"expr": "(LOWER(${Logs.content}) = $0$)",
11673+
"grouping_set": null,
11674+
}).to_string(),
11675+
]),
11676+
time_dimensions: None,
11677+
order: Some(vec![]),
11678+
limit: None,
11679+
offset: None,
11680+
filters: None,
11681+
ungrouped: None,
11682+
}
11683+
);
1162111684
}
1162211685

1162311686
#[tokio::test]
@@ -11871,20 +11934,46 @@ ORDER BY "source"."str0" ASC
1187111934
);
1187211935

1187311936
assert_eq!(
11874-
query_plan.as_logical_plan().find_cube_scan().request,
11937+
query_plan
11938+
.as_logical_plan()
11939+
.find_cube_scan_wrapper()
11940+
.request
11941+
.unwrap(),
1187511942
V1LoadRequestQuery {
1187611943
measures: Some(vec![]),
11877-
dimensions: Some(vec![]),
11878-
segments: Some(vec![]),
11944+
dimensions: Some(vec![
11945+
json!({
11946+
"cube_name": "KibanaSampleDataEcommerce",
11947+
"alias": "customer_gender",
11948+
"cube_params": ["KibanaSampleDataEcommerce"],
11949+
"expr": "${KibanaSampleDataEcommerce.customer_gender}",
11950+
"grouping_set": null,
11951+
}).to_string(),
11952+
json!({
11953+
"cube_name": "KibanaSampleDataEcommerce",
11954+
"alias": "cast_dateadd_utf",
11955+
"cube_params": ["KibanaSampleDataEcommerce"],
11956+
"expr": "CAST(DATE_ADD(${KibanaSampleDataEcommerce.order_date}, INTERVAL '2 DAY') AS DATE)",
11957+
"grouping_set": null,
11958+
}).to_string(),
11959+
json!({
11960+
"cube_name": "KibanaSampleDataEcommerce",
11961+
"alias": "dateadd_utf8__se",
11962+
"cube_params": ["KibanaSampleDataEcommerce"],
11963+
"expr": "DATE_ADD(${KibanaSampleDataEcommerce.order_date}, INTERVAL '2000000 MILLISECOND')",
11964+
"grouping_set": null,
11965+
}).to_string(),
11966+
]),
11967+
segments: Some(vec![
11968+
json!({
11969+
"cube_name": "KibanaSampleDataEcommerce",
11970+
"alias": "dateadd_utf8__da",
11971+
"cube_params": ["KibanaSampleDataEcommerce"],
11972+
"expr": "(DATE_ADD(${KibanaSampleDataEcommerce.order_date}, INTERVAL '2 DAY') < DATE('2014-06-02'))",
11973+
"grouping_set": null,
11974+
}).to_string(),
11975+
]),
1187911976
order: Some(vec![]),
11880-
filters: Some(vec![V1LoadRequestQueryFilterItem {
11881-
member: Some("KibanaSampleDataEcommerce.order_date".to_string(),),
11882-
operator: Some("beforeDate".to_string(),),
11883-
values: Some(vec!["2014-05-31T00:00:00.000Z".to_string()]),
11884-
or: None,
11885-
and: None,
11886-
}]),
11887-
ungrouped: Some(true),
1188811977
..Default::default()
1188911978
}
1189011979
)
@@ -12669,53 +12758,39 @@ ORDER BY "source"."str0" ASC
1266912758
.await
1267012759
.as_logical_plan();
1267112760

12672-
let end_date = chrono::Utc::now().date_naive() - chrono::Duration::days(1);
12673-
let start_date = end_date - chrono::Duration::days(29);
12761+
let end_date = chrono::Utc::now().date_naive();
12762+
let start_date = end_date - chrono::Duration::days(30);
1267412763
assert_eq!(
12675-
logical_plan.find_cube_scan().request,
12764+
logical_plan.find_cube_scan_wrapper().request.unwrap(),
1267612765
V1LoadRequestQuery {
12677-
measures: Some(vec![]),
12678-
dimensions: Some(vec![]),
12679-
segments: Some(vec![]),
12680-
time_dimensions: Some(vec![V1LoadRequestQueryTimeDimension {
12681-
dimension: "KibanaSampleDataEcommerce.order_date".to_string(),
12682-
granularity: None,
12683-
date_range: Some(json!(vec![
12684-
format!("{}T00:00:00.000Z", start_date),
12685-
format!("{}T23:59:59.999Z", end_date),
12686-
]))
12687-
}]),
12766+
measures: Some(vec![
12767+
json!({
12768+
"cube_name": "KibanaSampleDataEcommerce",
12769+
"alias": "avg_kibanasample",
12770+
"cube_params": ["KibanaSampleDataEcommerce"],
12771+
"expr": "AVG(${KibanaSampleDataEcommerce.avgPrice})",
12772+
"grouping_set": null,
12773+
}).to_string(),
12774+
]),
12775+
dimensions: Some(vec![
12776+
json!({
12777+
"cube_name": "KibanaSampleDataEcommerce",
12778+
"alias": "cast_kibanasampl",
12779+
"cube_params": ["KibanaSampleDataEcommerce"],
12780+
"expr": "CAST(${KibanaSampleDataEcommerce.order_date} AS DATE)",
12781+
"grouping_set": null,
12782+
}).to_string(),
12783+
]),
12784+
segments: Some(vec![
12785+
json!({
12786+
"cube_name": "KibanaSampleDataEcommerce",
12787+
"alias": "kibanasampledata",
12788+
"cube_params": ["KibanaSampleDataEcommerce"],
12789+
"expr": format!("(((${{KibanaSampleDataEcommerce.order_date}} >= DATE('{start_date}')) AND (${{KibanaSampleDataEcommerce.order_date}} < DATE('{end_date}'))) AND (((${{KibanaSampleDataEcommerce.notes}} = $0$) OR (${{KibanaSampleDataEcommerce.notes}} = $1$)) OR (${{KibanaSampleDataEcommerce.notes}} = $2$)))"),
12790+
"grouping_set": null,
12791+
}).to_string(),
12792+
]),
1268812793
order: Some(vec![]),
12689-
filters: Some(vec![V1LoadRequestQueryFilterItem {
12690-
member: None,
12691-
operator: None,
12692-
values: None,
12693-
or: Some(vec![
12694-
json!(V1LoadRequestQueryFilterItem {
12695-
member: Some("KibanaSampleDataEcommerce.notes".to_string()),
12696-
operator: Some("equals".to_string()),
12697-
values: Some(vec!["note1".to_string()]),
12698-
or: None,
12699-
and: None,
12700-
}),
12701-
json!(V1LoadRequestQueryFilterItem {
12702-
member: Some("KibanaSampleDataEcommerce.notes".to_string()),
12703-
operator: Some("equals".to_string()),
12704-
values: Some(vec!["note2".to_string()]),
12705-
or: None,
12706-
and: None,
12707-
}),
12708-
json!(V1LoadRequestQueryFilterItem {
12709-
member: Some("KibanaSampleDataEcommerce.notes".to_string()),
12710-
operator: Some("equals".to_string()),
12711-
values: Some(vec!["note3".to_string()]),
12712-
or: None,
12713-
and: None,
12714-
}),
12715-
]),
12716-
and: None
12717-
}]),
12718-
ungrouped: Some(true),
1271912794
..Default::default()
1272012795
}
1272112796
)

rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/merge.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,18 @@ impl WrapperRules {
124124
"?order_expr",
125125
"?select_alias",
126126
"?select_distinct",
127-
"?select_ungrouped",
127+
// this should inherit lower instead of higher
128+
// sematics is that "input of WS in ungrouped", and we use input from lower
129+
// lower WrappedSelect is simple, but if it's ungrouped, then
130+
// "?select_ungrouped",
131+
"WrappedSelectUngrouped:true",
128132
"?select_ungrouped_scan",
129133
),
130134
"?alias_to_cube",
131-
"WrapperPullupReplacerUngrouped:false",
135+
// TODO why fixed false? is
136+
// "WrapperPullupReplacerUngrouped:false",
137+
// "WrapperPullupReplacerUngrouped:true",
138+
"?ungrouped",
132139
"?in_projection",
133140
"?cube_members",
134141
),

0 commit comments

Comments
 (0)