@@ -19,9 +19,11 @@ use databend_common_catalog::runtime_filter_info::RuntimeFilterInfo;
19
19
use databend_common_exception:: ErrorCode ;
20
20
use databend_common_exception:: Result ;
21
21
use databend_common_expression:: type_check;
22
+ use databend_common_expression:: types:: DataType ;
22
23
use databend_common_expression:: types:: NumberDomain ;
23
24
use databend_common_expression:: types:: NumberScalar ;
24
25
use databend_common_expression:: Column ;
26
+ use databend_common_expression:: Constant ;
25
27
use databend_common_expression:: Domain ;
26
28
use databend_common_expression:: Expr ;
27
29
use databend_common_expression:: RawExpr ;
@@ -71,6 +73,13 @@ pub fn build_runtime_filter_infos(
71
73
}
72
74
73
75
fn build_inlist_filter ( inlist : Column , probe_key : & Expr < String > ) -> Result < Expr < String > > {
76
+ if inlist. len ( ) == 0 {
77
+ return Ok ( Expr :: Constant ( Constant {
78
+ span : None ,
79
+ scalar : Scalar :: Boolean ( false ) ,
80
+ data_type : DataType :: Boolean ,
81
+ } ) ) ;
82
+ }
74
83
let probe_key = probe_key. as_column_ref ( ) . unwrap ( ) ;
75
84
76
85
let raw_probe_key = RawExpr :: ColumnRef {
@@ -79,20 +88,47 @@ fn build_inlist_filter(inlist: Column, probe_key: &Expr<String>) -> Result<Expr<
79
88
data_type : probe_key. data_type . clone ( ) ,
80
89
display_name : probe_key. display_name . clone ( ) ,
81
90
} ;
82
- let array = RawExpr :: Constant {
91
+
92
+ let mut scalars = inlist. iter ( ) ;
93
+
94
+ let first_scalar = scalars. next ( ) . unwrap ( ) ;
95
+ let first_constant = RawExpr :: Constant {
83
96
span : None ,
84
- scalar : Scalar :: Array ( inlist ) ,
97
+ scalar : first_scalar . to_owned ( ) ,
85
98
data_type : None ,
86
99
} ;
87
-
88
- let args = vec ! [ array, raw_probe_key] ;
89
- let contain_func = RawExpr :: FunctionCall {
100
+ let mut or_expr = RawExpr :: FunctionCall {
90
101
span : None ,
91
- name : "contains " . to_string ( ) ,
102
+ name : "eq " . to_string ( ) ,
92
103
params : vec ! [ ] ,
93
- args,
104
+ args : vec ! [ raw_probe_key . clone ( ) , first_constant ] ,
94
105
} ;
95
- let expr = type_check:: check ( & contain_func, & BUILTIN_FUNCTIONS ) ?;
106
+
107
+ for scalar in scalars {
108
+ let constant_expr = RawExpr :: Constant {
109
+ span : None ,
110
+ scalar : scalar. to_owned ( ) ,
111
+ data_type : None ,
112
+ } ;
113
+
114
+ let eq_expr = RawExpr :: FunctionCall {
115
+ span : None ,
116
+ name : "eq" . to_string ( ) ,
117
+ params : vec ! [ ] ,
118
+ args : vec ! [ raw_probe_key. clone( ) , constant_expr] ,
119
+ } ;
120
+
121
+ or_expr = RawExpr :: FunctionCall {
122
+ span : None ,
123
+ name : "or" . to_string ( ) ,
124
+ params : vec ! [ ] ,
125
+ args : vec ! [ or_expr, eq_expr] ,
126
+ } ;
127
+ }
128
+
129
+ let final_expr = or_expr;
130
+
131
+ let expr = type_check:: check ( & final_expr, & BUILTIN_FUNCTIONS ) ?;
96
132
Ok ( expr)
97
133
}
98
134
@@ -188,3 +224,93 @@ fn build_bloom_filter(
188
224
let filter = BinaryFuse16 :: try_from ( & hashes_vec) ?;
189
225
Ok ( ( probe_key. id . to_string ( ) , filter) )
190
226
}
227
+
228
+ #[ cfg( test) ]
229
+ mod tests {
230
+ use std:: collections:: HashMap ;
231
+
232
+ use databend_common_expression:: types:: DataType ;
233
+ use databend_common_expression:: types:: NumberDataType ;
234
+ use databend_common_expression:: ColumnBuilder ;
235
+ use databend_common_expression:: ColumnRef ;
236
+ use databend_common_expression:: Constant ;
237
+ use databend_common_expression:: ConstantFolder ;
238
+ use databend_common_expression:: Domain ;
239
+ use databend_common_expression:: Expr ;
240
+ use databend_common_expression:: FunctionContext ;
241
+ use databend_common_expression:: Scalar ;
242
+ use databend_common_functions:: BUILTIN_FUNCTIONS ;
243
+
244
+ use super :: build_inlist_filter;
245
+
246
+ #[ test]
247
+ fn test_build_inlist_filter ( ) {
248
+ let func_ctx = FunctionContext :: default ( ) ;
249
+
250
+ // Create test column with values {1, 10}
251
+ let data_type = DataType :: Number ( NumberDataType :: Int32 ) ;
252
+ let mut builder = ColumnBuilder :: with_capacity ( & data_type, 2 ) ;
253
+ builder. push ( Scalar :: Number ( 1i32 . into ( ) ) . as_ref ( ) ) ;
254
+ builder. push ( Scalar :: Number ( 10i32 . into ( ) ) . as_ref ( ) ) ;
255
+ let inlist = builder. build ( ) ;
256
+
257
+ // Create probe key expression: column_a
258
+ let probe_key = Expr :: ColumnRef ( ColumnRef {
259
+ span : None ,
260
+ id : "column_a" . to_string ( ) ,
261
+ data_type : data_type. clone ( ) ,
262
+ display_name : "column_a" . to_string ( ) ,
263
+ } ) ;
264
+
265
+ // Build the filter expression
266
+ let filter_expr = build_inlist_filter ( inlist, & probe_key) . unwrap ( ) ;
267
+
268
+ // Test with ConstantFolder - case where column_a in [2,10] (can be folded to constant)
269
+ let mut input_domains = HashMap :: new ( ) ;
270
+ let domain_value_2_10 = Domain :: from_min_max (
271
+ Scalar :: Number ( 2i32 . into ( ) ) ,
272
+ Scalar :: Number ( 10i32 . into ( ) ) ,
273
+ & data_type,
274
+ ) ;
275
+ input_domains. insert ( "column_a" . to_string ( ) , domain_value_2_10) ;
276
+
277
+ let ( folded_expr, _) = ConstantFolder :: fold_with_domain (
278
+ & filter_expr,
279
+ & input_domains,
280
+ & func_ctx,
281
+ & BUILTIN_FUNCTIONS ,
282
+ ) ;
283
+
284
+ // Verify it's not folded to constant
285
+ assert ! ( folded_expr. as_constant( ) . is_none( ) ) ;
286
+
287
+ // Test with ConstantFolder - case where column_a in [2,9] (should evaluate to false)
288
+ let mut input_domains_false = HashMap :: new ( ) ;
289
+ let domain_value_2_9 = Domain :: from_min_max (
290
+ Scalar :: Number ( 2i32 . into ( ) ) ,
291
+ Scalar :: Number ( 9i32 . into ( ) ) ,
292
+ & data_type,
293
+ ) ;
294
+ input_domains_false. insert ( "column_a" . to_string ( ) , domain_value_2_9) ;
295
+
296
+ let ( folded_expr_false, _) = ConstantFolder :: fold_with_domain (
297
+ & filter_expr,
298
+ & input_domains_false,
299
+ & func_ctx,
300
+ & BUILTIN_FUNCTIONS ,
301
+ ) ;
302
+
303
+ // Range [2,9] does not intersect with {1, 10}, so it should fold to constant false
304
+ match folded_expr_false {
305
+ Expr :: Constant ( Constant {
306
+ scalar : Scalar :: Boolean ( false ) ,
307
+ ..
308
+ } ) => {
309
+ println ! ( "✓ Test passed: column_a in [2,9] correctly evaluated to false" ) ;
310
+ }
311
+ _ => {
312
+ panic ! ( "Expected constant false, got: {:?}" , folded_expr_false) ;
313
+ }
314
+ }
315
+ }
316
+ }
0 commit comments