Skip to content

Commit 5638f70

Browse files
authored
chore(cubesql): Fix date split column dependency
1 parent 20c8e89 commit 5638f70

File tree

2 files changed

+83
-42
lines changed

2 files changed

+83
-42
lines changed

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

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14344,12 +14344,9 @@ ORDER BY "source"."str0" ASC
1434414344

1434514345
#[tokio::test]
1434614346
async fn metabase_aggreagte_by_week_of_year() {
14347-
if !Rewriter::sql_push_down_enabled() {
14348-
return;
14349-
}
1435014347
init_logger();
1435114348

14352-
let query_plan = convert_select_to_query_plan(
14349+
let logical_plan = convert_select_to_query_plan(
1435314350
"SELECT ceil((CAST(extract(doy from CAST(date_trunc('week', \"KibanaSampleDataEcommerce\".\"order_date\") AS timestamp)) AS integer) / 7.0)) AS \"order_date\",
1435414351
min(\"KibanaSampleDataEcommerce\".\"minPrice\") AS \"min\"
1435514352
FROM \"KibanaSampleDataEcommerce\"
@@ -14358,23 +14355,27 @@ ORDER BY "source"."str0" ASC
1435814355
.to_string(),
1435914356
DatabaseProtocol::PostgreSQL,
1436014357
)
14361-
.await;
14358+
.await
14359+
.as_logical_plan();
1436214360

14363-
let physical_plan = query_plan.as_physical_plan().await.unwrap();
14364-
println!(
14365-
"Physical plan: {}",
14366-
displayable(physical_plan.as_ref()).indent()
14361+
assert_eq!(
14362+
logical_plan.find_cube_scan().request,
14363+
V1LoadRequestQuery {
14364+
measures: Some(vec!["KibanaSampleDataEcommerce.minPrice".to_string()]),
14365+
dimensions: Some(vec![]),
14366+
segments: Some(vec![]),
14367+
time_dimensions: Some(vec![V1LoadRequestQueryTimeDimension {
14368+
dimension: "KibanaSampleDataEcommerce.order_date".to_string(),
14369+
granularity: Some("week".to_string()),
14370+
date_range: None,
14371+
},]),
14372+
order: None,
14373+
limit: None,
14374+
offset: None,
14375+
filters: None,
14376+
ungrouped: None,
14377+
}
1436714378
);
14368-
14369-
let logical_plan = query_plan.as_logical_plan();
14370-
let sql = logical_plan
14371-
.find_cube_scan_wrapper()
14372-
.wrapped_sql
14373-
.unwrap()
14374-
.sql;
14375-
assert!(sql.contains("CEIL("));
14376-
assert!(sql.contains("EXTRACT("));
14377-
assert!(sql.contains("DATE_TRUNC("));
1437814379
}
1437914380

1438014381
#[tokio::test]

rust/cubesql/cubesql/src/compile/rewrite/rules/split/dates.rs

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
compile::rewrite::{
33
analysis::{ConstantFolding, LogicalPlanAnalysis},
4-
column_expr, literal_expr,
4+
cast_expr, literal_expr,
55
rules::{members::min_granularity, split::SplitRules, utils::parse_granularity_string},
66
LiteralExprValue, LogicalPlanLanguage,
77
},
@@ -18,13 +18,13 @@ impl SplitRules {
1818
|| {
1919
self.fun_expr(
2020
"DatePart",
21-
vec!["?granularity".to_string(), column_expr("?column")],
21+
vec!["?granularity".to_string(), "?expr".to_string()],
2222
)
2323
},
2424
|| {
2525
self.fun_expr(
2626
"DateTrunc",
27-
vec![literal_expr("?output_granularity"), column_expr("?column")],
27+
vec![literal_expr("?output_granularity"), "?expr".to_string()],
2828
)
2929
},
3030
|alias_column| {
@@ -46,27 +46,59 @@ impl SplitRules {
4646
"?outer_granularity".to_string(),
4747
self.fun_expr(
4848
"DateTrunc",
49-
vec!["?inner_granularity".to_string(), column_expr("?column")],
49+
vec!["?inner_granularity".to_string(), "?expr".to_string()],
5050
),
5151
],
5252
)
5353
},
54+
|| self.fun_expr("DateTrunc", vec!["?new_inner_granularity", "?expr"]),
55+
|alias_column| {
56+
self.fun_expr(
57+
"DatePart",
58+
vec!["?new_outer_granularity".to_string(), alias_column],
59+
)
60+
},
61+
self.transform_date_part_within_date_trunc(
62+
"?outer_granularity",
63+
"?inner_granularity",
64+
"?new_outer_granularity",
65+
"?new_inner_granularity",
66+
),
67+
false,
68+
rules,
69+
);
70+
self.single_arg_split_point_rules(
71+
"date-trunc-within-date-part-with-cast",
5472
|| {
5573
self.fun_expr(
56-
"DateTrunc",
57-
vec![literal_expr("?output_granularity"), column_expr("?column")],
74+
"DatePart",
75+
vec![
76+
"?outer_granularity".to_string(),
77+
cast_expr(
78+
self.fun_expr(
79+
"DateTrunc",
80+
vec!["?inner_granularity".to_string(), "?expr".to_string()],
81+
),
82+
"?cast_type",
83+
),
84+
],
5885
)
5986
},
87+
|| self.fun_expr("DateTrunc", vec!["?new_inner_granularity", "?expr"]),
6088
|alias_column| {
6189
self.fun_expr(
6290
"DatePart",
63-
vec![literal_expr("?output_granularity"), alias_column],
91+
vec![
92+
"?new_outer_granularity".to_string(),
93+
cast_expr(alias_column, "?cast_type"),
94+
],
6495
)
6596
},
6697
self.transform_date_part_within_date_trunc(
6798
"?outer_granularity",
6899
"?inner_granularity",
69-
"?output_granularity",
100+
"?new_outer_granularity",
101+
"?new_inner_granularity",
70102
),
71103
false,
72104
rules,
@@ -76,13 +108,13 @@ impl SplitRules {
76108
|| {
77109
self.fun_expr(
78110
"DateTrunc",
79-
vec![literal_expr("?granularity"), column_expr("?column")],
111+
vec![literal_expr("?granularity"), "?expr".to_string()],
80112
)
81113
},
82114
|| {
83115
self.fun_expr(
84116
"DateTrunc",
85-
vec![literal_expr("?granularity"), column_expr("?column")],
117+
vec![literal_expr("?granularity"), "?expr".to_string()],
86118
)
87119
},
88120
|alias_column| alias_column,
@@ -126,7 +158,8 @@ impl SplitRules {
126158
&self,
127159
outer_var: &str,
128160
inner_var: &str,
129-
granularity_var: &str,
161+
new_outer_var: &str,
162+
new_inner_var: &str,
130163
) -> impl Fn(
131164
bool,
132165
&mut egg::EGraph<LogicalPlanLanguage, LogicalPlanAnalysis>,
@@ -137,31 +170,38 @@ impl SplitRules {
137170
+ Clone {
138171
let outer_var = var!(outer_var);
139172
let inner_var = var!(inner_var);
140-
let granularity_var = var!(granularity_var);
173+
let new_outer_var = var!(new_outer_var);
174+
let new_inner_var = var!(new_inner_var);
141175
move |_, egraph, subst| {
142176
if let Some(ConstantFolding::Scalar(ScalarValue::Utf8(Some(outer_granularity)))) =
143177
&egraph[subst[outer_var]].data.constant
144178
{
145179
if let Some(ConstantFolding::Scalar(ScalarValue::Utf8(Some(inner_granularity)))) =
146180
&egraph[subst[inner_var]].data.constant
147181
{
182+
let Some(min_granularity) =
183+
min_granularity(&outer_granularity, &inner_granularity)
184+
else {
185+
subst.insert(new_outer_var, subst[outer_var]);
186+
subst.insert(new_inner_var, subst[inner_var]);
187+
return true;
188+
};
189+
148190
let date_trunc_granularity =
149-
match min_granularity(&outer_granularity, &inner_granularity) {
150-
Some(granularity) => {
151-
if granularity.to_lowercase() == inner_granularity.to_lowercase() {
152-
outer_granularity
153-
} else {
154-
inner_granularity
155-
}
156-
}
157-
None => return false,
191+
if min_granularity.to_lowercase() == inner_granularity.to_lowercase() {
192+
outer_granularity
193+
} else {
194+
inner_granularity
158195
};
159196

160-
let granularity =
197+
let granularity_value =
161198
egraph.add(LogicalPlanLanguage::LiteralExprValue(LiteralExprValue(
162199
ScalarValue::Utf8(Some(date_trunc_granularity.to_string())),
163200
)));
164-
subst.insert(granularity_var, granularity);
201+
let granularity =
202+
egraph.add(LogicalPlanLanguage::LiteralExpr([granularity_value]));
203+
subst.insert(new_outer_var, granularity);
204+
subst.insert(new_inner_var, granularity);
165205
return true;
166206
}
167207
}

0 commit comments

Comments
 (0)