@@ -47,17 +47,7 @@ impl PredicateBuilder {
4747 generics : _,
4848 args,
4949 return_type : _,
50- } if args. len ( ) == 1 && id. name ( ) . as_ref ( ) == "is_true" => {
51- let ( uncertain, predicate) = Self :: build ( & args[ 0 ] ) ;
52- if uncertain {
53- return ( uncertain, Predicate :: AlwaysTrue ) ;
54- }
55- match predicate {
56- Predicate :: AlwaysTrue => ( false , Predicate :: AlwaysTrue ) ,
57- Predicate :: AlwaysFalse => ( false , Predicate :: AlwaysFalse ) ,
58- _ => ( false , predicate) ,
59- }
60- }
50+ } if args. len ( ) == 1 && id. name ( ) . as_ref ( ) == "is_true" => Self :: build ( & args[ 0 ] ) ,
6151
6252 // unary
6353 RemoteExpr :: FunctionCall {
@@ -97,28 +87,39 @@ impl PredicateBuilder {
9787 ( false , predicate)
9888 }
9989
100- // binary {a op datum}
90+ // logical operators
10191 RemoteExpr :: FunctionCall {
10292 span : _,
10393 id,
10494 generics : _,
10595 args,
10696 return_type : _,
107- } if args. len ( ) = = 2
97+ } if args. len ( ) > = 2
10898 && [ "and" , "and_filters" , "or" , "or_filters" ] . contains ( & id. name ( ) . as_ref ( ) ) =>
10999 {
110- let ( left_uncertain, left) = Self :: build ( & args[ 0 ] ) ;
111- let ( right_uncertain, right) = Self :: build ( & args[ 1 ] ) ;
112- if left_uncertain || right_uncertain {
113- return ( true , Predicate :: AlwaysTrue ) ;
114- }
115- let predicate = match id. name ( ) . as_ref ( ) {
116- "and" | "and_filters" => left. and ( right) ,
117- "or" | "or_filters" => left. or ( right) ,
118- _ => unreachable ! ( ) ,
100+ let is_and = matches ! ( id. name( ) . as_ref( ) , "and" | "and_filters" ) ;
101+ let initial = if is_and {
102+ Predicate :: AlwaysTrue
103+ } else {
104+ Predicate :: AlwaysFalse
119105 } ;
120106
121- ( false , predicate)
107+ let mut uncertain = false ;
108+ let mut predicate = initial;
109+ for arg in args {
110+ let ( arg_uncertain, arg_predicate) = Self :: build ( arg) ;
111+ if !is_and && arg_uncertain {
112+ return ( true , Predicate :: AlwaysTrue ) ;
113+ }
114+ uncertain |= arg_uncertain;
115+ predicate = if is_and {
116+ predicate. and ( arg_predicate)
117+ } else {
118+ predicate. or ( arg_predicate)
119+ } ;
120+ }
121+
122+ ( uncertain, predicate)
122123 }
123124
124125 // binary {a op datum}
@@ -190,11 +191,11 @@ fn build_unary(r: Reference, op: &str) -> Option<Predicate> {
190191fn build_binary ( r : Reference , op : & str , datum : Datum ) -> Option < Predicate > {
191192 let op = match op {
192193 "lt" | "<" => r. less_than ( datum) ,
193- "le" | "<=" => r. less_than_or_equal_to ( datum) ,
194+ "le" | "lte" | " <=" => r. less_than_or_equal_to ( datum) ,
194195 "gt" | ">" => r. greater_than ( datum) ,
195- "ge" | ">=" => r. greater_than_or_equal_to ( datum) ,
196+ "ge" | "gte" | " >=" => r. greater_than_or_equal_to ( datum) ,
196197 "eq" | "=" => r. equal_to ( datum) ,
197- "ne" | "!=" => r. not_equal_to ( datum) ,
198+ "ne" | "noteq" | " !=" => r. not_equal_to ( datum) ,
198199 _ => return None ,
199200 } ;
200201 Some ( op)
@@ -204,11 +205,11 @@ fn build_binary(r: Reference, op: &str, datum: Datum) -> Option<Predicate> {
204205fn build_reverse_binary ( r : Reference , op : & str , datum : Datum ) -> Option < Predicate > {
205206 let op = match op {
206207 "lt" | "<" => r. greater_than ( datum) ,
207- "le" | "<=" => r. greater_than_or_equal_to ( datum) ,
208+ "le" | "lte" | " <=" => r. greater_than_or_equal_to ( datum) ,
208209 "gt" | ">" => r. less_than ( datum) ,
209- "ge" | ">=" => r. less_than_or_equal_to ( datum) ,
210+ "ge" | "gte" | " >=" => r. less_than_or_equal_to ( datum) ,
210211 "eq" | "=" => r. equal_to ( datum) ,
211- "ne" | "!=" => r. not_equal_to ( datum) ,
212+ "ne" | "noteq" | " !=" => r. not_equal_to ( datum) ,
212213 _ => return None ,
213214 } ;
214215 Some ( op)
@@ -238,3 +239,115 @@ fn scalar_to_datatum(scalar: &Scalar) -> Option<Datum> {
238239 } ;
239240 Some ( val)
240241}
242+
243+ #[ cfg( test) ]
244+ mod tests {
245+ use databend_common_expression:: FunctionID ;
246+
247+ use super :: * ;
248+
249+ fn column ( name : & str , data_type : DataType ) -> RemoteExpr < String > {
250+ RemoteExpr :: ColumnRef {
251+ span : None ,
252+ id : name. to_string ( ) ,
253+ data_type,
254+ display_name : name. to_string ( ) ,
255+ }
256+ }
257+
258+ fn constant ( scalar : Scalar , data_type : DataType ) -> RemoteExpr < String > {
259+ RemoteExpr :: Constant {
260+ span : None ,
261+ scalar,
262+ data_type,
263+ }
264+ }
265+
266+ fn function ( name : & str , args : Vec < RemoteExpr < String > > ) -> RemoteExpr < String > {
267+ RemoteExpr :: FunctionCall {
268+ span : None ,
269+ id : Box :: new ( FunctionID :: Builtin {
270+ name : name. to_string ( ) ,
271+ id : 0 ,
272+ } ) ,
273+ generics : vec ! [ ] ,
274+ args,
275+ return_type : DataType :: Boolean ,
276+ }
277+ }
278+
279+ fn string_eq ( column_name : & str , value : & str ) -> RemoteExpr < String > {
280+ function ( "eq" , vec ! [
281+ column( column_name, DataType :: String ) ,
282+ constant( Scalar :: String ( value. to_string( ) ) , DataType :: String ) ,
283+ ] )
284+ }
285+
286+ #[ test]
287+ fn test_build_databend_comparison_names ( ) {
288+ let timestamp = 1_784_197_641_000_000 ;
289+ let expr = function ( "gte" , vec ! [
290+ column( "report_time" , DataType :: Timestamp ) ,
291+ constant( Scalar :: Timestamp ( timestamp) , DataType :: Timestamp ) ,
292+ ] ) ;
293+
294+ let ( uncertain, predicate) = PredicateBuilder :: build ( & expr) ;
295+
296+ assert ! ( !uncertain) ;
297+ assert_eq ! (
298+ predicate,
299+ Reference :: new( "report_time" )
300+ . greater_than_or_equal_to( Datum :: timestamp_micros( timestamp) )
301+ ) ;
302+ }
303+
304+ #[ test]
305+ fn test_and_keeps_supported_conjuncts ( ) {
306+ let unsupported = function ( "unsupported" , vec ! [ column(
307+ "report_time" ,
308+ DataType :: Timestamp ,
309+ ) ] ) ;
310+ let event_name = string_eq ( "event_name" , "game_end" ) ;
311+ let expr = function ( "is_true" , vec ! [ function( "and_filters" , vec![
312+ unsupported,
313+ event_name,
314+ ] ) ] ) ;
315+
316+ let ( uncertain, predicate) = PredicateBuilder :: build ( & expr) ;
317+
318+ assert ! ( uncertain) ;
319+ assert_eq ! (
320+ predicate,
321+ Reference :: new( "event_name" ) . equal_to( Datum :: string( "game_end" ) )
322+ ) ;
323+ }
324+
325+ #[ test]
326+ fn test_variadic_and_builds_all_conjuncts ( ) {
327+ let expr = function ( "is_true" , vec ! [ function( "and_filters" , vec![
328+ string_eq( "event_name" , "game_end" ) ,
329+ string_eq( "source_flag" , "p7" ) ,
330+ string_eq( "page" , "home" ) ,
331+ ] ) ] ) ;
332+
333+ let ( uncertain, predicate) = PredicateBuilder :: build ( & expr) ;
334+
335+ assert ! ( !uncertain) ;
336+ assert_ne ! ( predicate, Predicate :: AlwaysTrue ) ;
337+ }
338+
339+ #[ test]
340+ fn test_or_drops_partial_predicate ( ) {
341+ let unsupported = function ( "unsupported" , vec ! [ column(
342+ "report_time" ,
343+ DataType :: Timestamp ,
344+ ) ] ) ;
345+ let event_name = string_eq ( "event_name" , "game_end" ) ;
346+ let expr = function ( "or_filters" , vec ! [ unsupported, event_name] ) ;
347+
348+ let ( uncertain, predicate) = PredicateBuilder :: build ( & expr) ;
349+
350+ assert ! ( uncertain) ;
351+ assert_eq ! ( predicate, Predicate :: AlwaysTrue ) ;
352+ }
353+ }
0 commit comments