@@ -27,40 +27,50 @@ pub enum ValueOrComposite {
27
27
impl ValueOrComposite {
28
28
pub fn into_sql < E > (
29
29
self ,
30
- prefix : Option < & str > ,
30
+ column_prefix : Option < & str > ,
31
31
validator : & dyn Fn ( & str ) -> Result < ( ) , E > ,
32
32
) -> Result < ( String , Vec < ( String , Value ) > ) , E > {
33
33
let mut index: usize = 0 ;
34
- return self . into_sql_impl ( prefix , validator, & mut index) ;
34
+ return self . into_sql_impl ( column_prefix , validator, & mut index) ;
35
35
}
36
36
37
37
fn into_sql_impl < E > (
38
38
self ,
39
- prefix : Option < & str > ,
39
+ column_prefix : Option < & str > ,
40
40
validator : & dyn Fn ( & str ) -> Result < ( ) , E > ,
41
41
index : & mut usize ,
42
42
) -> Result < ( String , Vec < ( String , Value ) > ) , E > {
43
43
match self {
44
44
Self :: Value ( v) => {
45
45
validator ( & v. column ) ?;
46
46
47
- let param = param_name ( * index) ;
48
- * index += 1 ;
47
+ return Ok ( if v. op . is_unary ( ) {
48
+ (
49
+ match column_prefix {
50
+ Some ( p) => format ! ( r#"{p}."{c}" {o}"# , c = v. column, o = v. op. to_sql( ) ) ,
51
+ None => format ! ( r#""{c}" {o}"# , c = v. column, o = v. op. to_sql( ) ) ,
52
+ } ,
53
+ vec ! [ ] ,
54
+ )
55
+ } else {
56
+ let param = param_name ( * index) ;
57
+ * index += 1 ;
49
58
50
- return Ok ( (
51
- match prefix {
52
- Some ( p) => format ! ( r#"{p}."{c}" {o} {param}"# , c = v. column, o = v. op. to_sql( ) ) ,
53
- None => format ! ( r#""{c}" {o} {param}"# , c = v. column, o = v. op. to_sql( ) ) ,
54
- } ,
55
- vec ! [ ( param, v. value) ] ,
56
- ) ) ;
59
+ (
60
+ match column_prefix {
61
+ Some ( p) => format ! ( r#"{p}."{c}" {o} {param}"# , c = v. column, o = v. op. to_sql( ) ) ,
62
+ None => format ! ( r#""{c}" {o} {param}"# , c = v. column, o = v. op. to_sql( ) ) ,
63
+ } ,
64
+ vec ! [ ( param, v. value) ] ,
65
+ )
66
+ } ) ;
57
67
}
58
68
Self :: Composite ( combiner, vec) => {
59
69
let mut fragments = Vec :: < String > :: with_capacity ( vec. len ( ) ) ;
60
70
let mut params = Vec :: < ( String , Value ) > :: with_capacity ( vec. len ( ) ) ;
61
71
62
72
for value_or_composite in vec {
63
- let ( f, p) = value_or_composite. into_sql_impl :: < E > ( prefix , validator, index) ?;
73
+ let ( f, p) = value_or_composite. into_sql_impl :: < E > ( column_prefix , validator, index) ?;
64
74
fragments. push ( f) ;
65
75
params. extend ( p) ;
66
76
}
@@ -270,4 +280,46 @@ mod tests {
270
280
qs. deserialize_str ( "filter[col0]=val0&filter[$and][0][col0]=val0&filter[col1]=val1" ) ;
271
281
assert ! ( m3. is_err( ) , "{m3:?}" ) ;
272
282
}
283
+
284
+ #[ test]
285
+ fn test_filter_to_sql ( ) {
286
+ let v0 = ValueOrComposite :: Value ( ColumnOpValue {
287
+ column : "col0" . to_string ( ) ,
288
+ op : CompareOp :: Equal ,
289
+ value : Value :: String ( "val0" . to_string ( ) ) ,
290
+ } ) ;
291
+
292
+ let validator = |_: & str | -> Result < ( ) , String > {
293
+ return Ok ( ( ) ) ;
294
+ } ;
295
+ let sql0 = v0
296
+ . clone ( )
297
+ . into_sql ( /* column_prefix= */ None , & validator)
298
+ . unwrap ( ) ;
299
+ assert_eq ! ( sql0. 0 , r#""col0" = :__p0"# ) ;
300
+ let sql0 = v0
301
+ . into_sql ( /* column_prefix= */ Some ( "p" ) , & validator)
302
+ . unwrap ( ) ;
303
+ assert_eq ! ( sql0. 0 , r#"p."col0" = :__p0"# ) ;
304
+
305
+ let v1 = ValueOrComposite :: Value ( ColumnOpValue {
306
+ column : "col0" . to_string ( ) ,
307
+ op : CompareOp :: Null ,
308
+ value : Value :: String ( "" . to_string ( ) ) ,
309
+ } ) ;
310
+ assert_eq ! (
311
+ v1. into_sql( None , & validator) . unwrap( ) . 0 ,
312
+ r#""col0" IS NULL"#
313
+ ) ;
314
+
315
+ let v2 = ValueOrComposite :: Value ( ColumnOpValue {
316
+ column : "col0" . to_string ( ) ,
317
+ op : CompareOp :: NotNull ,
318
+ value : Value :: String ( "ignored" . to_string ( ) ) ,
319
+ } ) ;
320
+ assert_eq ! (
321
+ v2. into_sql( Some ( "p" ) , & validator) . unwrap( ) . 0 ,
322
+ r#"p."col0" IS NOT NULL"#
323
+ ) ;
324
+ }
273
325
}
0 commit comments