Skip to content

Commit 2fcd242

Browse files
committed
feat(cubesql): Top-down extractor for rewrites
1 parent 4902e6f commit 2fcd242

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
@@ -14389,7 +14389,11 @@ ORDER BY "source"."str0" ASC
1438914389
.wrapped_sql
1439014390
.unwrap()
1439114391
.sql;
14392-
assert!(sql.contains("\"limit\":1000"));
14392+
if Rewriter::top_down_extractor_enabled() {
14393+
assert!(sql.contains("LIMIT 1000"));
14394+
} else {
14395+
assert!(sql.contains("\"limit\":1000"));
14396+
}
1439314397
assert!(sql.contains("% 7"));
1439414398

1439514399
let physical_plan = query_plan.as_physical_plan().await.unwrap();
@@ -15456,7 +15460,7 @@ ORDER BY "source"."str0" ASC
1545615460
FROM ({{ from }}) AS {{ from_alias }}
1545715461
{% if group_by %} GROUP BY {{ group_by | map(attribute='index') | join(', ') }}{% endif %}
1545815462
{% if order_by %} ORDER BY {{ order_by | map(attribute='expr') | join(', ') }}{% endif %}{% if offset %}
15459-
OFFSET {{ offset }}{% endif %}{% if limit %}
15463+
OFFSET {{ offset }}{% endif %}{% if limit is not none %}
1546015464
LIMIT {{ limit }}{% endif %}"#.to_string(),
1546115465
),
1546215466
]
@@ -16567,7 +16571,7 @@ LIMIT {{ limit }}{% endif %}"#.to_string(),
1656716571
measure(count) AS cnt,
1656816572
date_trunc('month', order_date) AS dt
1656916573
FROM KibanaSampleDataEcommerce
16570-
WHERE order_date IN (to_timestamp('2019-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US'))
16574+
WHERE date_trunc('month', order_date) IN (to_timestamp('2019-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.US'))
1657116575
GROUP BY 2
1657216576
;"#
1657316577
.to_string(),
@@ -16585,10 +16589,18 @@ LIMIT {{ limit }}{% endif %}"#.to_string(),
1658516589
time_dimensions: Some(vec![V1LoadRequestQueryTimeDimension {
1658616590
dimension: "KibanaSampleDataEcommerce.order_date".to_string(),
1658716591
granularity: Some("month".to_string()),
16588-
date_range: Some(json!(vec![
16589-
"2019-01-01T00:00:00.000Z".to_string(),
16590-
"2019-01-01T00:00:00.000Z".to_string()
16591-
]))
16592+
date_range: if Rewriter::top_down_extractor_enabled() {
16593+
Some(json!(vec![
16594+
"2019-01-01T00:00:00.000Z".to_string(),
16595+
"2019-01-31T23:59:59.999Z".to_string()
16596+
]))
16597+
} else {
16598+
// Non-optimal variant with top down extractor disabled
16599+
Some(json!(vec![
16600+
"2019-01-01 00:00:00.000".to_string(),
16601+
"2019-01-31 23:59:59.999".to_string()
16602+
]))
16603+
}
1659216604
}]),
1659316605
order: Some(vec![]),
1659416606
limit: None,
@@ -16935,4 +16947,35 @@ LIMIT {{ limit }}{% endif %}"#.to_string(),
1693516947

1693616948
Ok(())
1693716949
}
16950+
16951+
#[tokio::test]
16952+
async fn test_wrapper_limit_zero() {
16953+
if !Rewriter::sql_push_down_enabled() {
16954+
return;
16955+
}
16956+
init_testing_logger();
16957+
16958+
let query_plan = convert_select_to_query_plan(
16959+
r#"
16960+
SELECT MAX(order_date) FROM KibanaSampleDataEcommerce LIMIT 0
16961+
"#
16962+
.to_string(),
16963+
DatabaseProtocol::PostgreSQL,
16964+
)
16965+
.await;
16966+
16967+
let logical_plan = query_plan.as_logical_plan();
16968+
let sql = logical_plan
16969+
.find_cube_scan_wrapper()
16970+
.wrapped_sql
16971+
.unwrap()
16972+
.sql;
16973+
assert!(sql.contains("LIMIT 0"));
16974+
16975+
let physical_plan = query_plan.as_physical_plan().await.unwrap();
16976+
println!(
16977+
"Physical plan: {}",
16978+
displayable(physical_plan.as_ref()).indent()
16979+
);
16980+
}
1693816981
}

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)