Skip to content

Commit d2bdc1b

Browse files
authored
feat(cubesql): SQL push down support for synthetic fields (#7418)
1 parent b1606da commit d2bdc1b

File tree

4 files changed

+86
-13
lines changed

4 files changed

+86
-13
lines changed

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18869,6 +18869,44 @@ ORDER BY \"COUNT(count)\" DESC"
1886918869
);
1887018870
}
1887118871

18872+
#[tokio::test]
18873+
async fn test_case_wrapper_with_system_fields() {
18874+
if !Rewriter::sql_push_down_enabled() {
18875+
return;
18876+
}
18877+
init_logger();
18878+
18879+
let query_plan = convert_select_to_query_plan(
18880+
"SELECT CASE WHEN customer_gender = 'female' THEN 'f' ELSE 'm' END, __user, __cubeJoinField, AVG(avgPrice) mp FROM KibanaSampleDataEcommerce a GROUP BY 1, 2, 3 LIMIT 1123"
18881+
.to_string(),
18882+
DatabaseProtocol::PostgreSQL,
18883+
)
18884+
.await;
18885+
18886+
let logical_plan = query_plan.as_logical_plan();
18887+
18888+
assert!(
18889+
logical_plan
18890+
.find_cube_scan_wrapper()
18891+
.wrapped_sql
18892+
.unwrap()
18893+
.sql
18894+
.contains("__user:(KibanaSampleDataEcommerce):$"),
18895+
"SQL contains __user:(KibanaSampleDataEcommerce):$: {}",
18896+
logical_plan
18897+
.find_cube_scan_wrapper()
18898+
.wrapped_sql
18899+
.unwrap()
18900+
.sql
18901+
);
18902+
18903+
let physical_plan = query_plan.as_physical_plan().await.unwrap();
18904+
println!(
18905+
"Physical plan: {}",
18906+
displayable(physical_plan.as_ref()).indent()
18907+
);
18908+
}
18909+
1887218910
#[tokio::test]
1887318911
async fn test_case_wrapper_with_limit() {
1887418912
if !Rewriter::sql_push_down_enabled() {

rust/cubesql/cubesql/src/compile/rewrite/converter.rs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,18 +1343,33 @@ impl LanguageToLogicalPlanConverter {
13431343
))
13441344
})?;
13451345
for column in cube.get_columns() {
1346-
// TODO literal members and cube members
1347-
fields.push((
1348-
DFField::new(
1349-
Some(&alias),
1350-
column.get_name(),
1351-
column.get_column_type().to_arrow(),
1352-
true,
1353-
),
1354-
MemberField::Member(
1355-
column.member_name().to_string(),
1356-
),
1357-
));
1346+
if self.cube_context.meta.is_synthetic_field(
1347+
column.member_name().to_string(),
1348+
) {
1349+
fields.push((
1350+
DFField::new(
1351+
Some(&alias),
1352+
column.get_name(),
1353+
column.get_column_type().to_arrow(),
1354+
true,
1355+
),
1356+
MemberField::Literal(ScalarValue::Utf8(
1357+
None,
1358+
)),
1359+
));
1360+
} else {
1361+
fields.push((
1362+
DFField::new(
1363+
Some(&alias),
1364+
column.get_name(),
1365+
column.get_column_type().to_arrow(),
1366+
true,
1367+
),
1368+
MemberField::Member(
1369+
column.member_name().to_string(),
1370+
),
1371+
));
1372+
}
13581373
}
13591374
}
13601375
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,11 @@ impl WrapperRules {
6666
.iter()
6767
.find(|(cn, _)| cn == &column.name)
6868
{
69-
if let Some(_) = cube_context
69+
if cube_context
7070
.meta
7171
.find_dimension_with_name(member.to_string())
72+
.is_some()
73+
|| cube_context.meta.is_synthetic_field(member.to_string())
7274
{
7375
let column_expr_column =
7476
egraph.add(LogicalPlanLanguage::ColumnExprColumn(

rust/cubesql/cubesql/src/transport/ctx.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,24 @@ impl MetaContext {
169169
}
170170
}
171171

172+
pub fn is_synthetic_field(&self, name: String) -> bool {
173+
let cube_and_member_name = name.split(".").collect::<Vec<_>>();
174+
if cube_and_member_name.len() == 1
175+
&& MetaContext::is_synthetic_field_name(cube_and_member_name[0])
176+
{
177+
return true;
178+
}
179+
if let Some(_) = self.find_cube_with_name(cube_and_member_name[0]) {
180+
MetaContext::is_synthetic_field_name(cube_and_member_name[1])
181+
} else {
182+
false
183+
}
184+
}
185+
186+
pub fn is_synthetic_field_name(field_name: &str) -> bool {
187+
field_name == "__user" || field_name == "__cubeJoinField"
188+
}
189+
172190
pub fn find_df_data_type(&self, member_name: String) -> Option<DataType> {
173191
self.find_cube_with_name(member_name.split(".").next()?)?
174192
.df_data_type(member_name.as_str())

0 commit comments

Comments
 (0)