Skip to content

Commit

Permalink
feat(cubesql): Support Substring for rewriting (Metabase) (#4881)
Browse files Browse the repository at this point in the history
  • Loading branch information
ovr committed Jul 10, 2022
1 parent 83b4c09 commit 8fadebd
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 0 deletions.
34 changes: 34 additions & 0 deletions rust/cubesql/cubesql/src/compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8889,6 +8889,40 @@ ORDER BY \"COUNT(count)\" DESC"
Ok(())
}

#[tokio::test]
async fn test_metabase_substring() -> Result<(), CubeError> {
let query_plan = convert_select_to_query_plan(
"SELECT
\"source\".\"substring1\" AS \"substring2\",
\"source\".\"count\" AS \"count\"
FROM (
SELECT
\"KibanaSampleDataEcommerce\".\"count\" AS \"count\",
SUBSTRING(\"KibanaSampleDataEcommerce\".\"customer_gender\" FROM 1 FOR 1234) AS \"substring1\"
FROM
\"public\".\"KibanaSampleDataEcommerce\"
) AS \"source\"".to_string(),
DatabaseProtocol::PostgreSQL,
).await;

let logical_plan = query_plan.as_logical_plan();
assert_eq!(
logical_plan.find_cube_scan().request,
V1LoadRequestQuery {
measures: Some(vec!["KibanaSampleDataEcommerce.count".to_string(),]),
segments: Some(vec![]),
dimensions: Some(vec!["KibanaSampleDataEcommerce.customer_gender".to_string()]),
time_dimensions: None,
order: None,
limit: None,
offset: None,
filters: None,
}
);

Ok(())
}

#[tokio::test]
async fn test_subquery_with_same_name_excel() -> Result<(), CubeError> {
insta::assert_snapshot!(
Expand Down
127 changes: 127 additions & 0 deletions rust/cubesql/cubesql/src/compile/rewrite/rules/split.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,51 @@ impl RewriteRules for SplitRules {
"?projection_alias",
),
),
// TODO: Aggregation on top of Projection to re-aggregate results after projection modifying
transforming_rewrite(
"split-projection-projection-aggr",
projection(
"?expr",
cube_scan(
"?source_table_name",
"?members",
"?filters",
"?orders",
"?limit",
"?offset",
"?aliases",
"?table_name",
"CubeScanSplit:false",
),
"?alias",
),
projection(
outer_aggregate_split_replacer("?expr", "?outer_aggregate_cube"),
projection(
inner_aggregate_split_replacer("?expr", "?inner_aggregate_cube"),
cube_scan(
"?source_table_name",
"?members",
"?filters",
"?orders",
"?limit",
"?offset",
"?aliases",
"?table_name",
"CubeScanSplit:true",
),
"?projection_alias",
),
"?alias",
),
self.split_projection_projection_aggregate(
"?source_table_name",
"?inner_aggregate_cube",
"?outer_aggregate_cube",
"?table_name",
"?projection_alias",
),
),
transforming_rewrite(
"split-aggregate-aggregate",
aggregate(
Expand Down Expand Up @@ -260,6 +305,14 @@ impl RewriteRules for SplitRules {
outer_aggregate_split_replacer("?right", "?cube"),
),
),
rewrite(
"split-push-down-projection-outer-aggr-replacer",
outer_aggregate_split_replacer(projection_expr("?left", "?right"), "?cube"),
projection_expr(
outer_aggregate_split_replacer("?left", "?cube"),
outer_aggregate_split_replacer("?right", "?cube"),
),
),
rewrite(
"split-push-down-group-outer-aggr-replacer-tail",
outer_aggregate_split_replacer(aggr_group_expr_empty_tail(), "?cube"),
Expand All @@ -270,6 +323,11 @@ impl RewriteRules for SplitRules {
outer_aggregate_split_replacer(aggr_aggr_expr_empty_tail(), "?cube"),
aggr_aggr_expr_empty_tail(),
),
rewrite(
"split-push-down-projection-outer-aggr-replacer-tail",
outer_aggregate_split_replacer(projection_expr_empty_tail(), "?cube"),
projection_expr_empty_tail(),
),
// Members
// Column rules
rewrite(
Expand Down Expand Up @@ -525,6 +583,30 @@ impl RewriteRules for SplitRules {
"?data_type",
),
),
// Substring
rewrite(
"split-push-down-substr-inner-replacer",
inner_aggregate_split_replacer(
fun_expr("Substr", vec!["?expr", "?from", "?to"]),
"?cube",
),
inner_aggregate_split_replacer("?expr", "?cube"),
),
rewrite(
"split-push-down-substr-outer-aggr-replacer",
outer_aggregate_split_replacer(
fun_expr("Substr", vec!["?expr", "?from", "?to"]),
"?cube",
),
fun_expr(
"Substr",
vec![
outer_aggregate_split_replacer("?expr", "?cube"),
"?from".to_string(),
"?to".to_string(),
],
),
),
// Alias
rewrite(
"split-push-down-alias-inner-replacer",
Expand Down Expand Up @@ -680,6 +762,51 @@ impl SplitRules {
}
}

fn split_projection_projection_aggregate(
&self,
cube_expr_var: &'static str,
inner_aggregate_cube_expr_var: &'static str,
outer_aggregate_cube_expr_var: &'static str,
table_name_var: &'static str,
projection_alias_var: &'static str,
) -> impl Fn(&mut EGraph<LogicalPlanLanguage, LogicalPlanAnalysis>, &mut Subst) -> bool {
let cube_expr_var = var!(cube_expr_var);
let inner_aggregate_cube_expr_var = var!(inner_aggregate_cube_expr_var);
let outer_aggregate_cube_expr_var = var!(outer_aggregate_cube_expr_var);
let table_name_var = var!(table_name_var);
let projection_alias_var = var!(projection_alias_var);
move |egraph, subst| {
for cube in var_iter!(egraph[subst[cube_expr_var]], TableScanSourceTableName).cloned() {
for table_name in
var_iter!(egraph[subst[table_name_var]], CubeScanTableName).cloned()
{
subst.insert(
projection_alias_var,
egraph.add(LogicalPlanLanguage::ProjectionAlias(ProjectionAlias(Some(
table_name.to_string(),
)))),
);

subst.insert(
inner_aggregate_cube_expr_var,
egraph.add(LogicalPlanLanguage::InnerAggregateSplitReplacerCube(
InnerAggregateSplitReplacerCube(cube.to_string()),
)),
);

subst.insert(
outer_aggregate_cube_expr_var,
egraph.add(LogicalPlanLanguage::OuterAggregateSplitReplacerCube(
OuterAggregateSplitReplacerCube(cube.to_string()),
)),
);
return true;
}
}
false
}
}

fn split_projection_aggregate(
&self,
cube_expr_var: &'static str,
Expand Down

0 comments on commit 8fadebd

Please sign in to comment.