Skip to content

Commit c54113c

Browse files
committed
feat(cubesql): Top-down extractor for rewrites
1 parent 8fa0d53 commit c54113c

File tree

11 files changed

+652
-220
lines changed

11 files changed

+652
-220
lines changed

packages/cubejs-backend-native/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3217,7 +3217,7 @@ export class BaseQuery {
32173217
'{% if filter %}\nWHERE {{ filter }}{% endif %}' +
32183218
'{% if group_by %}\nGROUP BY {{ group_by }}{% endif %}' +
32193219
'{% if order_by %}\nORDER BY {{ order_by | map(attribute=\'expr\') | join(\', \') }}{% endif %}' +
3220-
'{% if limit %}\nLIMIT {{ limit }}{% endif %}' +
3220+
'{% if limit is not none %}\nLIMIT {{ limit }}{% endif %}' +
32213221
'{% if offset %}\nOFFSET {{ offset }}{% endif %}',
32223222
group_by_exprs: '{{ group_by | map(attribute=\'index\') | join(\', \') }}',
32233223
},

packages/cubejs-schema-compiler/src/adapter/PrestodbQuery.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export class PrestodbQuery extends BaseQuery {
117117
'{% if group_by %} GROUP BY {{ group_by }}{% endif %}' +
118118
'{% if order_by %} ORDER BY {{ order_by | map(attribute=\'expr\') | join(\', \') }}{% endif %}' +
119119
'{% if offset %}\nOFFSET {{ offset }}{% endif %}' +
120-
'{% if limit %}\nLIMIT {{ limit }}{% endif %}';
120+
'{% if limit is not none %}\nLIMIT {{ limit }}{% endif %}';
121121
templates.expressions.extract = 'EXTRACT({{ date_part }} FROM {{ expr }})';
122122
templates.expressions.interval_single_date_part = 'INTERVAL \'{{ num }}\' {{ date_part }}';
123123
templates.expressions.timestamp_literal = 'from_iso8601_timestamp(\'{{ value }}\')';

rust/cubesql/Cargo.lock

Lines changed: 8 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/cubesql/cubesql/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ minijinja = { version = "1", features = ["json", "loader"] }
5858
lru = "0.12.1"
5959
sha2 = "0.10.8"
6060
bigdecimal = "0.4.2"
61+
indexmap = "1.9.3"
6162

6263

6364
[dev-dependencies]

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

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16042,7 +16042,11 @@ ORDER BY "source"."str0" ASC
1604216042
.wrapped_sql
1604316043
.unwrap()
1604416044
.sql;
16045-
assert!(sql.contains("\"limit\":1000"));
16045+
if Rewriter::top_down_extractor_enabled() {
16046+
assert!(sql.contains("LIMIT 1000"));
16047+
} else {
16048+
assert!(sql.contains("\"limit\":1000"));
16049+
}
1604616050
assert!(sql.contains("% 7"));
1604716051

1604816052
let physical_plan = query_plan.as_physical_plan().await.unwrap();
@@ -17109,7 +17113,7 @@ ORDER BY "source"."str0" ASC
1710917113
FROM ({{ from }}) AS {{ from_alias }}
1711017114
{% if group_by %} GROUP BY {{ group_by | map(attribute='index') | join(', ') }}{% endif %}
1711117115
{% if order_by %} ORDER BY {{ order_by | map(attribute='expr') | join(', ') }}{% endif %}{% if offset %}
17112-
OFFSET {{ offset }}{% endif %}{% if limit %}
17116+
OFFSET {{ offset }}{% endif %}{% if limit is not none %}
1711317117
LIMIT {{ limit }}{% endif %}"#.to_string(),
1711417118
),
1711517119
]
@@ -18220,7 +18224,7 @@ LIMIT {{ limit }}{% endif %}"#.to_string(),
1822018224
measure(count) AS cnt,
1822118225
date_trunc('month', order_date) AS dt
1822218226
FROM KibanaSampleDataEcommerce
18223-
WHERE order_date IN (to_timestamp('2019-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US'))
18227+
WHERE date_trunc('month', order_date) IN (to_timestamp('2019-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US'))
1822418228
GROUP BY 2
1822518229
;"#
1822618230
.to_string(),
@@ -18238,10 +18242,18 @@ LIMIT {{ limit }}{% endif %}"#.to_string(),
1823818242
time_dimensions: Some(vec![V1LoadRequestQueryTimeDimension {
1823918243
dimension: "KibanaSampleDataEcommerce.order_date".to_string(),
1824018244
granularity: Some("month".to_string()),
18241-
date_range: Some(json!(vec![
18242-
"2019-01-01T00:00:00.000Z".to_string(),
18243-
"2019-01-01T00:00:00.000Z".to_string()
18244-
]))
18245+
date_range: if Rewriter::top_down_extractor_enabled() {
18246+
Some(json!(vec![
18247+
"2019-01-01T00:00:00.000Z".to_string(),
18248+
"2019-01-31T23:59:59.999Z".to_string()
18249+
]))
18250+
} else {
18251+
// Non-optimal variant with top down extractor disabled
18252+
Some(json!(vec![
18253+
"2019-01-01 00:00:00.000".to_string(),
18254+
"2019-01-31 23:59:59.999".to_string()
18255+
]))
18256+
}
1824518257
}]),
1824618258
order: Some(vec![]),
1824718259
limit: None,
@@ -18588,4 +18600,35 @@ LIMIT {{ limit }}{% endif %}"#.to_string(),
1858818600

1858918601
Ok(())
1859018602
}
18603+
18604+
#[tokio::test]
18605+
async fn test_wrapper_limit_zero() {
18606+
if !Rewriter::sql_push_down_enabled() {
18607+
return;
18608+
}
18609+
init_testing_logger();
18610+
18611+
let query_plan = convert_select_to_query_plan(
18612+
r#"
18613+
SELECT MAX(order_date) FROM KibanaSampleDataEcommerce LIMIT 0
18614+
"#
18615+
.to_string(),
18616+
DatabaseProtocol::PostgreSQL,
18617+
)
18618+
.await;
18619+
18620+
let logical_plan = query_plan.as_logical_plan();
18621+
let sql = logical_plan
18622+
.find_cube_scan_wrapper()
18623+
.wrapped_sql
18624+
.unwrap()
18625+
.sql;
18626+
assert!(sql.contains("LIMIT 0"));
18627+
18628+
let physical_plan = query_plan.as_physical_plan().await.unwrap();
18629+
println!(
18630+
"Physical plan: {}",
18631+
displayable(physical_plan.as_ref()).indent()
18632+
);
18633+
}
1859118634
}

rust/cubesql/cubesql/src/compile/query_engine.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,13 @@ pub trait QueryEngine {
186186
let mut rewriter = Rewriter::new(finalized_graph, cube_ctx.clone());
187187

188188
let result = rewriter
189-
.find_best_plan(root, state.auth_context().unwrap(), qtrace, span_id.clone())
189+
.find_best_plan(
190+
root,
191+
state.auth_context().unwrap(),
192+
qtrace,
193+
span_id.clone(),
194+
self.config_ref().top_down_extractor(),
195+
)
190196
.await
191197
.map_err(|e| match e.cause {
192198
CubeErrorCauseType::Internal(_) => CompilationError::Internal(

0 commit comments

Comments
 (0)