@@ -157,13 +157,10 @@ impl<'a> Evaluator<'a> {
157157 ..
158158 } if function. signature . name == "if" => self . eval_if ( args, generics, validity) ,
159159
160- Expr :: FunctionCall {
161- function,
162- args,
163- generics,
164- ..
165- } if function. signature . name == "and_filters" => {
166- self . eval_and_filters ( args, generics, validity)
160+ Expr :: FunctionCall { function, args, .. }
161+ if function. signature . name == "and_filters" =>
162+ {
163+ self . eval_and_filters ( args, validity)
167164 }
168165
169166 Expr :: FunctionCall {
@@ -812,11 +809,10 @@ impl<'a> Evaluator<'a> {
812809 }
813810 }
814811
815- // `and_filters` is a special builtin function similar to `if` that could partially
812+ // `and_filters` is a special builtin function similar to `if` that conditionally evaluate its arguments.
816813 fn eval_and_filters (
817814 & self ,
818815 args : & [ Expr ] ,
819- _: & [ DataType ] ,
820816 mut validity : Option < Bitmap > ,
821817 ) -> Result < Value < AnyType > > {
822818 assert ! ( args. len( ) >= 2 ) ;
@@ -850,7 +846,8 @@ impl<'a> Evaluator<'a> {
850846 }
851847 }
852848
853- /// Evaluate a set returning function. Return multiple chunks of results, and the repeat times of each of the result.
849+ /// Evaluate a set-returning-function. Return multiple sets of results
850+ /// for each input row, along with the number of rows in each set.
854851 pub fn run_srf ( & self , expr : & Expr ) -> Result < Vec < ( Value < AnyType > , usize ) > > {
855852 if let Expr :: FunctionCall {
856853 function,
@@ -866,7 +863,9 @@ impl<'a> Evaluator<'a> {
866863 . map ( |expr| self . run ( expr) )
867864 . collect :: < Result < Vec < _ > > > ( ) ?;
868865 let cols_ref = args. iter ( ) . map ( Value :: as_ref) . collect :: < Vec < _ > > ( ) ;
869- return Ok ( ( eval) ( & cols_ref, self . input_columns . num_rows ( ) ) ) ;
866+ let result = ( eval) ( & cols_ref, self . input_columns . num_rows ( ) ) ;
867+ assert_eq ! ( result. len( ) , self . input_columns. num_rows( ) ) ;
868+ return Ok ( result) ;
870869 }
871870 }
872871
@@ -1005,7 +1004,7 @@ impl<'a, Index: ColumnIndex> ConstantFolder<'a, Index> {
10051004 scalar,
10061005 data_type : dest_type. clone ( ) ,
10071006 } ,
1008- new_domain ,
1007+ None ,
10091008 ) ;
10101009 }
10111010 }
@@ -1032,68 +1031,109 @@ impl<'a, Index: ColumnIndex> ConstantFolder<'a, Index> {
10321031 return_type,
10331032 } if function. signature . name == "and_filters" => {
10341033 let mut args_expr = Vec :: new ( ) ;
1035- let mut has_true = true ;
1036- let mut has_false = true ;
1034+ let mut result_domain = Some ( BooleanDomain {
1035+ has_true : true ,
1036+ has_false : true ,
1037+ } ) ;
10371038
10381039 type DomainType = NullableType < BooleanType > ;
10391040 for arg in args {
10401041 let ( expr, domain) = self . fold_once ( arg) ;
1042+ // A temporary hack to make `and_filters` shortcut on false.
1043+ // TODO(andylokandy): make it a rule in the optimizer.
1044+ if let Expr :: Constant {
1045+ scalar : Scalar :: Boolean ( false ) ,
1046+ ..
1047+ } = & expr
1048+ {
1049+ return (
1050+ Expr :: Constant {
1051+ span : * span,
1052+ scalar : Scalar :: Boolean ( false ) ,
1053+ data_type : DataType :: Boolean ,
1054+ } ,
1055+ None ,
1056+ ) ;
1057+ }
10411058 args_expr. push ( expr) ;
10421059
1043- match domain {
1044- Some ( domain) => {
1045- let domain = DomainType :: try_downcast_domain ( & domain) . unwrap ( ) ;
1046- let ( domain_hash_true, domain_hash_false) = match & domain {
1047- NullableDomain {
1048- has_null,
1049- value :
1050- Some ( box BooleanDomain {
1051- has_true,
1052- has_false,
1053- } ) ,
1054- } => ( * has_true, * has_null || * has_false) ,
1055- NullableDomain { value : None , .. } => ( false , true ) ,
1056- } ;
1057-
1058- has_true = has_true && domain_hash_true;
1059- has_false = has_false || domain_hash_false;
1060- }
1061- None => {
1062- continue ;
1060+ result_domain = result_domain. zip ( domain) . map ( |( func_domain, domain) | {
1061+ let domain = DomainType :: try_downcast_domain ( & domain) . unwrap ( ) ;
1062+ let ( domain_has_true, domain_has_false) = match & domain {
1063+ NullableDomain {
1064+ has_null,
1065+ value :
1066+ Some ( box BooleanDomain {
1067+ has_true,
1068+ has_false,
1069+ } ) ,
1070+ } => ( * has_true, * has_null || * has_false) ,
1071+ NullableDomain { value : None , .. } => ( false , true ) ,
1072+ } ;
1073+ BooleanDomain {
1074+ has_true : func_domain. has_true && domain_has_true,
1075+ has_false : func_domain. has_false || domain_has_false,
10631076 }
1077+ } ) ;
1078+
1079+ if let Some ( Scalar :: Boolean ( false ) ) = result_domain
1080+ . as_ref ( )
1081+ . and_then ( |domain| Domain :: Boolean ( * domain) . as_singleton ( ) )
1082+ {
1083+ return (
1084+ Expr :: Constant {
1085+ span : * span,
1086+ scalar : Scalar :: Boolean ( false ) ,
1087+ data_type : DataType :: Boolean ,
1088+ } ,
1089+ None ,
1090+ ) ;
10641091 }
10651092 }
10661093
1067- if !has_true && has_false {
1068- (
1094+ if let Some ( scalar) = result_domain
1095+ . as_ref ( )
1096+ . and_then ( |domain| Domain :: Boolean ( * domain) . as_singleton ( ) )
1097+ {
1098+ return (
10691099 Expr :: Constant {
10701100 span : * span,
1071- scalar : Scalar :: Boolean ( false ) ,
1101+ scalar,
10721102 data_type : DataType :: Boolean ,
10731103 } ,
1074- Some ( Domain :: Boolean ( BooleanDomain {
1075- has_true : false ,
1076- has_false : true ,
1077- } ) ) ,
1078- )
1079- } else {
1080- let func_expr = Expr :: FunctionCall {
1081- span : * span,
1082- id : id. clone ( ) ,
1083- function : function. clone ( ) ,
1084- generics : generics. clone ( ) ,
1085- args : args_expr,
1086- return_type : return_type. clone ( ) ,
1087- } ;
1088-
1089- (
1090- func_expr,
1091- Some ( Domain :: Boolean ( BooleanDomain {
1092- has_true,
1093- has_false,
1094- } ) ) ,
1095- )
1104+ None ,
1105+ ) ;
10961106 }
1107+
1108+ let all_args_is_scalar = args_expr. iter ( ) . all ( |arg| arg. as_constant ( ) . is_some ( ) ) ;
1109+
1110+ let func_expr = Expr :: FunctionCall {
1111+ span : * span,
1112+ id : id. clone ( ) ,
1113+ function : function. clone ( ) ,
1114+ generics : generics. clone ( ) ,
1115+ args : args_expr,
1116+ return_type : return_type. clone ( ) ,
1117+ } ;
1118+
1119+ if all_args_is_scalar {
1120+ let block = DataBlock :: empty ( ) ;
1121+ let evaluator = Evaluator :: new ( & block, self . func_ctx , self . fn_registry ) ;
1122+ // Since we know the expression is constant, it'll be safe to change its column index type.
1123+ let func_expr = func_expr. project_column_ref ( |_| unreachable ! ( ) ) ;
1124+ if let Ok ( Value :: Scalar ( scalar) ) = evaluator. run ( & func_expr) {
1125+ return (
1126+ Expr :: Constant {
1127+ span : * span,
1128+ scalar,
1129+ data_type : return_type. clone ( ) ,
1130+ } ,
1131+ None ,
1132+ ) ;
1133+ }
1134+ }
1135+
1136+ ( func_expr, result_domain. map ( Domain :: Boolean ) )
10971137 }
10981138 Expr :: FunctionCall {
10991139 span,
@@ -1143,7 +1183,7 @@ impl<'a, Index: ColumnIndex> ConstantFolder<'a, Index> {
11431183 scalar,
11441184 data_type : return_type. clone ( ) ,
11451185 } ,
1146- func_domain ,
1186+ None ,
11471187 ) ;
11481188 }
11491189
@@ -1159,7 +1199,7 @@ impl<'a, Index: ColumnIndex> ConstantFolder<'a, Index> {
11591199 scalar,
11601200 data_type : return_type. clone ( ) ,
11611201 } ,
1162- func_domain ,
1202+ None ,
11631203 ) ;
11641204 }
11651205 }
0 commit comments