@@ -31,6 +31,7 @@ use crate::{
31
31
} ,
32
32
} ,
33
33
config:: ConfigObj ,
34
+ sql:: ColumnType ,
34
35
transport:: { MetaContext , V1CubeMetaDimensionExt , V1CubeMetaExt , V1CubeMetaMeasureExt } ,
35
36
var, var_iter, var_list_iter, CubeError ,
36
37
} ;
@@ -527,6 +528,23 @@ impl MemberRules {
527
528
relation,
528
529
) ,
529
530
) ,
531
+ // Cast without alias will not generate stable name in schema, so there's no rule like that for now
532
+ // TODO implement it anyway, to be able to remove Projection on top of CubeScan completely
533
+ transforming_rewrite(
534
+ & format!( "member-pushdown-replacer-column-{}-cast-alias" , name) ,
535
+ member_pushdown_replacer(
536
+ alias_expr( cast_expr( column_expr( "?column" ) , "?cast_type" ) , "?alias" ) ,
537
+ member_fn( "?old_alias" ) ,
538
+ "?member_pushdown_replacer_alias_to_cube" ,
539
+ ) ,
540
+ member_fn( "?output_column" ) ,
541
+ self . transform_alias(
542
+ "?member_pushdown_replacer_alias_to_cube" ,
543
+ "?alias" ,
544
+ "?output_column" ,
545
+ relation,
546
+ ) ,
547
+ ) ,
530
548
]
531
549
}
532
550
@@ -541,7 +559,10 @@ impl MemberRules {
541
559
} ;
542
560
543
561
let find_matching_old_member =
544
- |name : & str , column_expr : String , column_to_search : ColumnToSearch | {
562
+ |name : & str ,
563
+ column_expr : String ,
564
+ column_to_search : ColumnToSearch ,
565
+ cast_type_var : Option < & ' static str > | {
545
566
transforming_rewrite (
546
567
& format ! (
547
568
"member-pushdown-replacer-column-find-matching-old-member-{}" ,
@@ -560,6 +581,7 @@ impl MemberRules {
560
581
self . transform_find_matching_old_member (
561
582
"?member_pushdown_replacer_alias_to_cube" ,
562
583
column_to_search,
584
+ cast_type_var,
563
585
"?old_members" ,
564
586
"?terminal_member" ,
565
587
"?filtered_member_pushdown_replacer_alias_to_cube" ,
@@ -610,16 +632,31 @@ impl MemberRules {
610
632
"column" ,
611
633
column_expr ( "?column" ) ,
612
634
ColumnToSearch :: Var ( "?column" ) ,
635
+ None ,
636
+ ) ) ;
637
+ rules. push ( find_matching_old_member (
638
+ "column-cast" ,
639
+ cast_expr ( column_expr ( "?column" ) , "?cast_type" ) ,
640
+ ColumnToSearch :: Var ( "?column" ) ,
641
+ Some ( "?cast_type" ) ,
613
642
) ) ;
614
643
rules. push ( find_matching_old_member (
615
644
"alias" ,
616
645
alias_expr ( column_expr ( "?column" ) , "?alias" ) ,
617
646
ColumnToSearch :: Var ( "?column" ) ,
647
+ None ,
648
+ ) ) ;
649
+ rules. push ( find_matching_old_member (
650
+ "alias-cast" ,
651
+ alias_expr ( cast_expr ( column_expr ( "?column" ) , "?cast_type" ) , "?alias" ) ,
652
+ ColumnToSearch :: Var ( "?column" ) ,
653
+ Some ( "?cast_type" ) ,
618
654
) ) ;
619
655
rules. push ( find_matching_old_member (
620
656
"agg-fun" ,
621
657
agg_fun_expr ( "?fun_name" , vec ! [ column_expr( "?column" ) ] , "?distinct" ) ,
622
658
ColumnToSearch :: Var ( "?column" ) ,
659
+ None ,
623
660
) ) ;
624
661
rules. push ( find_matching_old_member (
625
662
"agg-fun-alias" ,
@@ -628,11 +665,13 @@ impl MemberRules {
628
665
"?alias" ,
629
666
) ,
630
667
ColumnToSearch :: Var ( "?column" ) ,
668
+ None ,
631
669
) ) ;
632
670
rules. push ( find_matching_old_member (
633
671
"udaf-fun" ,
634
672
udaf_expr ( MEASURE_UDAF_NAME , vec ! [ column_expr( "?column" ) ] ) ,
635
673
ColumnToSearch :: Var ( "?column" ) ,
674
+ None ,
636
675
) ) ;
637
676
rules. push ( find_matching_old_member (
638
677
"agg-fun-default-count" ,
@@ -642,6 +681,7 @@ impl MemberRules {
642
681
"AggregateFunctionExprDistinct:false" ,
643
682
) ,
644
683
ColumnToSearch :: DefaultCount ,
684
+ None ,
645
685
) ) ;
646
686
rules. push ( find_matching_old_member (
647
687
"agg-fun-default-count-alias" ,
@@ -654,6 +694,7 @@ impl MemberRules {
654
694
"?alias" ,
655
695
) ,
656
696
ColumnToSearch :: DefaultCount ,
697
+ None ,
657
698
) ) ;
658
699
rules. push ( find_matching_old_member (
659
700
"agg-fun-with-cast" ,
@@ -664,6 +705,7 @@ impl MemberRules {
664
705
"?distinct" ,
665
706
) ,
666
707
ColumnToSearch :: Var ( "?column" ) ,
708
+ None ,
667
709
) ) ;
668
710
rules. push ( find_matching_old_member (
669
711
"date-trunc" ,
@@ -672,6 +714,7 @@ impl MemberRules {
672
714
vec ! [ literal_expr( "?granularity" ) , column_expr( "?column" ) ] ,
673
715
) ,
674
716
ColumnToSearch :: Var ( "?column" ) ,
717
+ None ,
675
718
) ) ;
676
719
rules. push ( find_matching_old_member (
677
720
"date-trunc-with-alias" ,
@@ -684,6 +727,7 @@ impl MemberRules {
684
727
"?original_alias" ,
685
728
) ,
686
729
ColumnToSearch :: Var ( "?column" ) ,
730
+ None ,
687
731
) ) ;
688
732
Self :: measure_rewrites (
689
733
& mut rules,
@@ -1955,10 +1999,47 @@ impl MemberRules {
1955
1999
)
1956
2000
}
1957
2001
2002
+ fn can_remove_cast (
2003
+ meta : & MetaContext ,
2004
+ member : & Member ,
2005
+ cast_types : Option < & Vec < DataType > > ,
2006
+ ) -> bool {
2007
+ let cube = member. cube ( ) ;
2008
+ match cast_types {
2009
+ // No cast, nothing to check
2010
+ None => true ,
2011
+ // Need to check that cast is trivial
2012
+ Some ( cast_types) => {
2013
+ // For now, allow trivial casts only for cube members, not literals
2014
+ let Some ( cube) = & cube else {
2015
+ return false ;
2016
+ } ;
2017
+ let Some ( name) = member. name ( ) else {
2018
+ return false ;
2019
+ } ;
2020
+ let Some ( cube) = meta. find_cube_with_name ( cube) else {
2021
+ return false ;
2022
+ } ;
2023
+ // For now, allow trivial casts only for dimensions
2024
+ let Some ( dimension) = cube. lookup_dimension_by_member_name ( name) else {
2025
+ return false ;
2026
+ } ;
2027
+
2028
+ cast_types
2029
+ . iter ( )
2030
+ . any ( |dt| match ( dimension. get_sql_type ( ) , dt) {
2031
+ ( ColumnType :: String , DataType :: Utf8 ) => true ,
2032
+ _ => false ,
2033
+ } )
2034
+ }
2035
+ }
2036
+ }
2037
+
1958
2038
fn transform_find_matching_old_member (
1959
2039
& self ,
1960
2040
member_pushdown_replacer_alias_to_cube_var : & ' static str ,
1961
2041
column_to_search : ColumnToSearch ,
2042
+ cast_type_var : Option < & ' static str > ,
1962
2043
old_members_var : & ' static str ,
1963
2044
terminal_member : & ' static str ,
1964
2045
filtered_member_pushdown_replacer_alias_to_cube_var : & ' static str ,
@@ -1969,18 +2050,27 @@ impl MemberRules {
1969
2050
ColumnToSearch :: Var ( column_var) => Some ( var ! ( column_var) ) ,
1970
2051
ColumnToSearch :: DefaultCount => None ,
1971
2052
} ;
2053
+ let cast_type_var = cast_type_var. map ( |cast_type_var| var ! ( cast_type_var) ) ;
1972
2054
let old_members_var = var ! ( old_members_var) ;
1973
2055
let terminal_member = var ! ( terminal_member) ;
1974
2056
let filtered_member_pushdown_replacer_alias_to_cube_var =
1975
2057
var ! ( filtered_member_pushdown_replacer_alias_to_cube_var) ;
1976
2058
let flat_list = self . config_obj . push_down_pull_up_split ( ) ;
2059
+ let meta = self . meta_context . clone ( ) ;
1977
2060
move |egraph, subst| {
1978
2061
let alias_to_cubes: Vec < _ > = var_iter ! (
1979
2062
egraph[ subst[ member_pushdown_replacer_alias_to_cube_var] ] ,
1980
2063
MemberPushdownReplacerAliasToCube
1981
2064
)
1982
2065
. cloned ( )
1983
2066
. collect ( ) ;
2067
+
2068
+ let cast_types = cast_type_var. map ( |cast_type_var| {
2069
+ var_iter ! ( egraph[ subst[ cast_type_var] ] , CastExprDataType )
2070
+ . cloned ( )
2071
+ . collect :: < Vec < _ > > ( )
2072
+ } ) ;
2073
+
1984
2074
for alias_to_cube in alias_to_cubes {
1985
2075
let column_iter = match column_var {
1986
2076
Some ( column_var) => var_iter ! ( egraph[ subst[ column_var] ] , ColumnExprColumn )
@@ -1996,7 +2086,9 @@ impl MemberRules {
1996
2086
. data
1997
2087
. find_member_by_alias ( & alias_name)
1998
2088
{
1999
- let cube_to_filter = if let Some ( cube) = member. 1 . cube ( ) {
2089
+ let member = & member. 1 ;
2090
+
2091
+ let cube_to_filter = if let Some ( cube) = member. cube ( ) {
2000
2092
Some ( cube)
2001
2093
} else {
2002
2094
alias_to_cube
@@ -2014,8 +2106,12 @@ impl MemberRules {
2014
2106
alias_to_cube. clone ( )
2015
2107
} ;
2016
2108
2109
+ if !Self :: can_remove_cast ( & meta, member, cast_types. as_ref ( ) ) {
2110
+ continue ;
2111
+ }
2112
+
2017
2113
// TODO remove unwrap
2018
- let old_member = member. 1 . clone ( ) . add_to_egraph ( egraph, flat_list) . unwrap ( ) ;
2114
+ let old_member = member. clone ( ) . add_to_egraph ( egraph, flat_list) . unwrap ( ) ;
2019
2115
subst. insert ( terminal_member, old_member) ;
2020
2116
2021
2117
let filtered_member_pushdown_replacer_alias_to_cube =
0 commit comments