Skip to content

Commit 97e54e0

Browse files
authored
fix(cubesql): Support concatenating non-strings in SQL push down for Athena/Presto (#9853)
Signed-off-by: Alex Qyoun-ae <[email protected]>
1 parent 2ada27d commit 97e54e0

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ export class PrestodbQuery extends BaseQuery {
136136
const templates = super.sqlTemplates();
137137
templates.functions.DATETRUNC = 'DATE_TRUNC({{ args_concat }})';
138138
templates.functions.DATEPART = 'DATE_PART({{ args_concat }})';
139+
templates.functions.CURRENTDATE = 'CURRENT_DATE';
139140
delete templates.functions.PERCENTILECONT;
140141
templates.statements.select = '{% if ctes %} WITH \n' +
141142
'{{ ctes | join(\',\n\') }}\n' +
@@ -153,6 +154,10 @@ export class PrestodbQuery extends BaseQuery {
153154
templates.expressions.extract = 'EXTRACT({{ date_part }} FROM {{ expr }})';
154155
templates.expressions.interval_single_date_part = 'INTERVAL \'{{ num }}\' {{ date_part }}';
155156
templates.expressions.timestamp_literal = 'from_iso8601_timestamp(\'{{ value }}\')';
157+
// Presto requires concat types to be VARCHAR
158+
templates.expressions.binary = '{% if op == \'||\' %}' +
159+
'CAST({{ left }} AS VARCHAR) || CAST({{ right }} AS VARCHAR)' +
160+
'{% else %}{{ left }} {{ op }} {{ right }}{% endif %}';
156161
delete templates.expressions.ilike;
157162
templates.types.string = 'VARCHAR';
158163
templates.types.float = 'REAL';

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17223,4 +17223,48 @@ LIMIT {{ limit }}{% endif %}"#.to_string(),
1722317223
}
1722417224
)
1722517225
}
17226+
17227+
#[tokio::test]
17228+
async fn test_athena_concat_numbers() {
17229+
if !Rewriter::sql_push_down_enabled() {
17230+
return;
17231+
}
17232+
init_testing_logger();
17233+
17234+
let query_plan = convert_select_to_query_plan_customized(
17235+
r#"
17236+
SELECT
17237+
CAST(EXTRACT(YEAR FROM "ta_1"."order_date") || '-' || 1 || '-01' AS DATE) AS "ca_1",
17238+
COALESCE(sum("ta_1"."sumPrice"), 0) AS "ca_2"
17239+
FROM "ovr"."public"."KibanaSampleDataEcommerce" AS "ta_1"
17240+
WHERE ((
17241+
EXTRACT(DAY FROM "ta_1"."order_date") <= EXTRACT(DAY FROM CURRENT_DATE)
17242+
AND EXTRACT(MONTH FROM "ta_1"."order_date") = EXTRACT(MONTH FROM CURRENT_DATE)
17243+
))
17244+
GROUP BY "ca_1"
17245+
ORDER BY "ca_1" ASC NULLS LAST
17246+
LIMIT 5000
17247+
"#
17248+
.to_string(),
17249+
DatabaseProtocol::PostgreSQL,
17250+
vec![(
17251+
"expressions/binary".to_string(),
17252+
"'{% if op == \'||\' %}CAST({{ left }} AS VARCHAR) || \
17253+
CAST({{ right }} AS VARCHAR)\
17254+
{% else %}{{ left }} {{ op }} {{ right }}{% endif %}'"
17255+
.to_string(),
17256+
)],
17257+
)
17258+
.await;
17259+
17260+
let physical_plan = query_plan.as_physical_plan().await.unwrap();
17261+
println!(
17262+
"Physical plan: {}",
17263+
displayable(physical_plan.as_ref()).indent()
17264+
);
17265+
17266+
let logical_plan = query_plan.as_logical_plan();
17267+
let sql = logical_plan.find_cube_scan_wrapped_sql().wrapped_sql.sql;
17268+
assert!(sql.contains("CAST(1 AS VARCHAR)"));
17269+
}
1722617270
}

0 commit comments

Comments
 (0)