Skip to content

Commit 18ec4fc

Browse files
authored
fix(cubesql): Fix Tableau relative dates (#9641)
1 parent 9bcb5a1 commit 18ec4fc

File tree

2 files changed

+136
-8
lines changed

2 files changed

+136
-8
lines changed

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

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16875,4 +16875,71 @@ LIMIT {{ limit }}{% endif %}"#.to_string(),
1687516875
}
1687616876
)
1687716877
}
16878+
16879+
#[tokio::test]
16880+
async fn test_tableau_relative_dates() {
16881+
init_testing_logger();
16882+
16883+
let logical_plan = convert_select_to_query_plan(
16884+
r#"
16885+
SELECT
16886+
CAST("KibanaSampleDataEcommerce"."customer_gender" AS TEXT) AS "customer_gendder",
16887+
SUM("KibanaSampleDataEcommerce"."sumPrice") AS "sum:sumPrice:ok"
16888+
FROM
16889+
"public"."KibanaSampleDataEcommerce" "KibanaSampleDataEcommerce"
16890+
WHERE
16891+
(
16892+
CASE
16893+
WHEN (
16894+
NOT (
16895+
CAST(
16896+
CAST(
16897+
TO_TIMESTAMP(
16898+
CAST(
16899+
CAST("KibanaSampleDataEcommerce"."order_date" AS TEXT) AS TEXT
16900+
),
16901+
'YYYY-MM-DD"T"HH24:MI:SS.MS'
16902+
) AS TIMESTAMP
16903+
) AS DATE
16904+
) IS NULL
16905+
)
16906+
) THEN CAST(
16907+
CAST(
16908+
TO_TIMESTAMP(
16909+
CAST(
16910+
CAST("KibanaSampleDataEcommerce"."order_date" AS TEXT) AS TEXT
16911+
),
16912+
'YYYY-MM-DD"T"HH24:MI:SS.MS'
16913+
) AS TIMESTAMP
16914+
) AS DATE
16915+
)
16916+
ELSE NULL
16917+
END
16918+
) < (TIMESTAMP '2025-01-01 00:00:00.000')
16919+
GROUP BY
16920+
1
16921+
"#
16922+
.to_string(),
16923+
DatabaseProtocol::PostgreSQL,
16924+
)
16925+
.await
16926+
.as_logical_plan();
16927+
16928+
assert_eq!(
16929+
logical_plan.find_cube_scan().request,
16930+
V1LoadRequestQuery {
16931+
measures: Some(vec!["KibanaSampleDataEcommerce.sumPrice".to_string()]),
16932+
dimensions: Some(vec!["KibanaSampleDataEcommerce.customer_gender".to_string()]),
16933+
segments: Some(vec![]),
16934+
order: Some(vec![]),
16935+
filters: Some(vec![V1LoadRequestQueryFilterItem {
16936+
member: Some("KibanaSampleDataEcommerce.order_date".to_string()),
16937+
operator: Some("beforeDate".to_string()),
16938+
values: Some(vec!["2025-01-01T00:00:00.000Z".to_string()]),
16939+
..Default::default()
16940+
}]),
16941+
..Default::default()
16942+
}
16943+
)
16944+
}
1687816945
}

rust/cubesql/cubesql/src/compile/rewrite/rules/filters.rs

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ use crate::{
33
compile::rewrite::{
44
alias_expr,
55
analysis::{ConstantFolding, Member, OriginalExpr},
6-
between_expr, binary_expr, case_expr, case_expr_var_arg, cast_expr, change_user_member,
7-
column_expr, cube_scan, cube_scan_filters, cube_scan_filters_empty_tail, cube_scan_members,
8-
dimension_expr, expr_column_name, filter, filter_member, filter_op, filter_op_filters,
9-
filter_op_filters_empty_tail, filter_replacer, filter_simplify_pull_up_replacer,
10-
filter_simplify_push_down_replacer, fun_expr, fun_expr_args_legacy, fun_expr_var_arg,
11-
inlist_expr, inlist_expr_list, is_not_null_expr, is_null_expr, like_expr, limit,
12-
list_rewrite, literal_bool, literal_expr, literal_int, literal_string, measure_expr,
13-
negative_expr, not_expr, projection, rewrite,
6+
between_expr, binary_expr, case_expr, case_expr_var_arg, cast_expr, cast_expr_explicit,
7+
change_user_member, column_expr, cube_scan, cube_scan_filters,
8+
cube_scan_filters_empty_tail, cube_scan_members, dimension_expr, expr_column_name, filter,
9+
filter_member, filter_op, filter_op_filters, filter_op_filters_empty_tail, filter_replacer,
10+
filter_simplify_pull_up_replacer, filter_simplify_push_down_replacer, fun_expr,
11+
fun_expr_args_legacy, fun_expr_var_arg, inlist_expr, inlist_expr_list, is_not_null_expr,
12+
is_null_expr, like_expr, limit, list_rewrite, literal_bool, literal_expr, literal_int,
13+
literal_null, literal_string, measure_expr, negative_expr, not_expr, projection, rewrite,
1414
rewriter::{CubeEGraph, CubeRewrite, RewriteRules},
1515
scalar_fun_expr_args_empty_tail, segment_member, time_dimension_date_range_replacer,
1616
time_dimension_expr, transform_original_expr_to_alias, transforming_chain_rewrite,
@@ -2461,6 +2461,67 @@ impl RewriteRules for FilterRules {
24612461
),
24622462
self.transform_not_column_equals_date("?literal", "?one_day"),
24632463
),
2464+
rewrite(
2465+
"filter-tableau-case-when-not-null",
2466+
filter_replacer(
2467+
binary_expr(
2468+
case_expr(
2469+
None,
2470+
vec![(
2471+
not_expr(is_null_expr("?left_expr")),
2472+
"?left_expr".to_string(),
2473+
)],
2474+
Some(literal_null()),
2475+
),
2476+
"?op",
2477+
"?right_expr",
2478+
),
2479+
"?alias_to_cube",
2480+
"?members",
2481+
"?filter_aliases",
2482+
),
2483+
filter_replacer(
2484+
binary_expr("?left_expr", "?op", "?right_expr"),
2485+
"?alias_to_cube",
2486+
"?members",
2487+
"?filter_aliases",
2488+
),
2489+
),
2490+
rewrite(
2491+
"filter-tableau-cast-text-to-timestamp-to-date",
2492+
filter_replacer(
2493+
binary_expr(
2494+
cast_expr_explicit(
2495+
udf_expr(
2496+
"str_to_date",
2497+
vec![
2498+
column_expr("?column"),
2499+
literal_string("YYYY-MM-DD\"T\"HH24:MI:SS.MS"),
2500+
],
2501+
),
2502+
DataType::Date32,
2503+
),
2504+
"?op",
2505+
"?right_expr",
2506+
),
2507+
"?alias_to_cube",
2508+
"?members",
2509+
"?filter_aliases",
2510+
),
2511+
filter_replacer(
2512+
binary_expr(
2513+
self.fun_expr(
2514+
"DateTrunc",
2515+
vec![literal_string("day"), column_expr("?column")],
2516+
),
2517+
"?op",
2518+
"?right_expr",
2519+
),
2520+
"?alias_to_cube",
2521+
"?members",
2522+
"?filter_aliases",
2523+
),
2524+
),
24642525
rewrite(
24652526
"in-date-range-to-time-dimension-pull-up-left",
24662527
cube_scan_filters(

0 commit comments

Comments
 (0)