• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

getdozer / dozer / 4293179261

pending completion
4293179261

push

github

GitHub
fix: Fix order of columns in schema (#1090)

28382 of 38590 relevant lines covered (73.55%)

38014.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

56.51
/dozer-sql/src/pipeline/expression/comparison.rs
1
use crate::pipeline::errors::PipelineError;
2
use dozer_types::rust_decimal::Decimal;
3
use dozer_types::types::Schema;
4
use dozer_types::{
5
    ordered_float::OrderedFloat,
6
    types::{Field, Record},
7
};
8
use num_traits::cast::*;
9

10
use crate::pipeline::expression::execution::{Expression, ExpressionExecutor};
11

12
macro_rules! define_comparison {
13
    ($id:ident, $op:expr, $function:expr) => {
14
        pub fn $id(
15,064✔
15
            schema: &Schema,
15,064✔
16
            left: &Expression,
15,064✔
17
            right: &Expression,
15,064✔
18
            record: &Record,
15,064✔
19
        ) -> Result<Field, PipelineError> {
15,064✔
20
            let left_p = left.evaluate(&record, schema)?;
15,064✔
21
            let right_p = right.evaluate(&record, schema)?;
15,064✔
22

23
            match left_p {
15,064✔
24
                Field::Null => match right_p {
30✔
25
                    // left: Null, right: Null
26
                    Field::Null => Ok(Field::Boolean(true)),
×
27
                    _ => Ok(Field::Boolean(false)),
30✔
28
                },
29
                Field::Boolean(left_v) => match right_p {
1✔
30
                    // left: Bool, right: Bool
31
                    Field::Boolean(right_v) => Ok(Field::Boolean($function(left_v, right_v))),
1✔
32
                    _ => Ok(Field::Boolean(false)),
×
33
                },
34
                Field::Int(left_v) => match right_p {
2,021✔
35
                    // left: Int, right: Int
36
                    Field::Int(right_v) => Ok(Field::Boolean($function(left_v, right_v))),
2,020✔
37
                    // left: Int, right: UInt
38
                    Field::UInt(right_v) => Ok(Field::Boolean($function(
×
39
                        left_v,
×
40
                        right_v
×
41
                            .to_i64()
×
42
                            .ok_or(PipelineError::InvalidOperandType(format!(
×
43
                                "Unable to cast {} to i64",
×
44
                                right_v
×
45
                            )))?,
×
46
                    ))),
47
                    // left: Int, right: Float
48
                    Field::Float(right_v) => {
1✔
49
                        let left_v_f = OrderedFloat::<f64>::from_i64(left_v).unwrap();
1✔
50
                        Ok(Field::Boolean($function(left_v_f, right_v)))
1✔
51
                    }
52
                    // left: Int, right: Decimal
53
                    Field::Decimal(right_v) => {
×
54
                        let left_v_d =
×
55
                            Decimal::from_i64(left_v).ok_or(PipelineError::InvalidOperandType(
×
56
                                format!("Unable to cast {} to decimal", left_v),
×
57
                            ))?;
×
58
                        Ok(Field::Boolean($function(left_v_d, right_v)))
×
59
                    }
60
                    // left: Int, right: Null
61
                    Field::Null => Ok(Field::Boolean(false)),
×
62
                    _ => Err(PipelineError::InvalidOperandType($op.to_string())),
×
63
                },
64
                Field::UInt(left_v) => match right_p {
2✔
65
                    // left: UInt, right: Int
66
                    Field::Int(right_v) => Ok(Field::Boolean($function(
×
67
                        left_v
×
68
                            .to_i64()
×
69
                            .ok_or(PipelineError::InvalidOperandType(format!(
×
70
                                "Unable to cast {} to i64",
×
71
                                left_v
×
72
                            )))?,
×
73
                        right_v,
×
74
                    ))),
75
                    // left: UInt, right: UInt
76
                    Field::UInt(right_v) => Ok(Field::Boolean($function(left_v, right_v))),
1✔
77
                    // left: UInt, right: Float
78
                    Field::Float(right_v) => {
×
79
                        let left_v_f = OrderedFloat::<f64>::from_i64(left_v.to_i64().ok_or(
×
80
                            PipelineError::InvalidOperandType(format!(
×
81
                                "Unable to cast {} to i64",
×
82
                                left_v
×
83
                            )),
×
84
                        )?)
×
85
                        .unwrap();
×
86
                        Ok(Field::Boolean($function(left_v_f, right_v)))
×
87
                    }
88
                    // left: UInt, right: Decimal
89
                    Field::Decimal(right_v) => {
×
90
                        let left_v_d = Decimal::from_i64(left_v.to_i64().ok_or(
×
91
                            PipelineError::InvalidOperandType(format!(
×
92
                                "Unable to cast {} to i64",
×
93
                                left_v
×
94
                            )),
×
95
                        )?)
×
96
                        .ok_or(PipelineError::InvalidOperandType(format!(
×
97
                            "Unable to cast {} to decimal",
×
98
                            left_v
×
99
                        )))?;
×
100
                        Ok(Field::Boolean($function(left_v_d, right_v)))
×
101
                    }
102
                    // left: UInt, right: Null
103
                    Field::Null => Ok(Field::Boolean(false)),
1✔
104
                    _ => Err(PipelineError::InvalidOperandType($op.to_string())),
×
105
                },
106
                Field::Float(left_v) => match right_p {
10,004✔
107
                    // left: Float, right: Float
108
                    Field::Float(right_v) => Ok(Field::Boolean($function(left_v, right_v))),
1✔
109
                    // left: Float, right: Int
110
                    Field::UInt(right_v) => {
×
111
                        let right_v_f = OrderedFloat::<f64>::from_i64(right_v.to_i64().ok_or(
×
112
                            PipelineError::InvalidOperandType(format!(
×
113
                                "Unable to cast {} to i64",
×
114
                                right_v
×
115
                            )),
×
116
                        )?)
×
117
                        .unwrap();
×
118
                        Ok(Field::Boolean($function(left_v, right_v_f)))
×
119
                    }
120
                    // left: Float, right: Int
121
                    Field::Int(right_v) => {
10,001✔
122
                        let right_v_f = OrderedFloat::<f64>::from_i64(right_v).unwrap();
10,001✔
123
                        Ok(Field::Boolean($function(left_v, right_v_f)))
10,001✔
124
                    }
125
                    // left: Float, right: Decimal
126
                    Field::Decimal(right_v) => {
×
127
                        let left_v_d = Decimal::from_f64(left_v.to_f64().ok_or(
×
128
                            PipelineError::InvalidOperandType(format!(
×
129
                                "Unable to cast {} to f64",
×
130
                                left_v
×
131
                            )),
×
132
                        )?)
×
133
                        .ok_or(PipelineError::InvalidOperandType(format!(
×
134
                            "Unable to cast {} to decimal",
×
135
                            left_v
×
136
                        )))?;
×
137
                        Ok(Field::Boolean($function(left_v_d, right_v)))
×
138
                    }
139
                    // left: Float, right: Null
140
                    Field::Null => Ok(Field::Boolean(false)),
2✔
141
                    _ => Err(PipelineError::InvalidOperandType($op.to_string())),
×
142
                },
143
                Field::Decimal(left_v) => match right_p {
4✔
144
                    // left: Decimal, right: Float
145
                    Field::Float(right_v) => {
×
146
                        let right_v_d = Decimal::from_f64(right_v.to_f64().ok_or(
×
147
                            PipelineError::InvalidOperandType(format!(
×
148
                                "Unable to cast {} to f64",
×
149
                                left_v
×
150
                            )),
×
151
                        )?)
×
152
                        .ok_or(PipelineError::InvalidOperandType(format!(
×
153
                            "Unable to cast {} to decimal",
×
154
                            right_v
×
155
                        )))?;
×
156
                        Ok(Field::Boolean($function(left_v, right_v_d)))
×
157
                    }
158
                    // left: Decimal, right: Int
159
                    Field::Int(right_v) => {
1✔
160
                        let right_v_d =
1✔
161
                            Decimal::from_i64(right_v).ok_or(PipelineError::InvalidOperandType(
1✔
162
                                format!("Unable to cast {} to decimal", right_v),
1✔
163
                            ))?;
1✔
164
                        Ok(Field::Boolean($function(left_v, right_v_d)))
1✔
165
                    }
166
                    // left: Decimal, right: UInt
167
                    Field::UInt(right_v) => {
1✔
168
                        let right_v_d = Decimal::from_i64(right_v.to_i64().ok_or(
1✔
169
                            PipelineError::InvalidOperandType(format!(
1✔
170
                                "Unable to cast {} to i64",
1✔
171
                                right_v
1✔
172
                            )),
1✔
173
                        )?)
1✔
174
                        .ok_or(PipelineError::InvalidOperandType(format!(
1✔
175
                            "Unable to cast {} to decimal",
1✔
176
                            right_v
1✔
177
                        )))?;
1✔
178
                        Ok(Field::Boolean($function(left_v, right_v_d)))
1✔
179
                    }
180
                    // left: Decimal, right: Decimal
181
                    Field::Decimal(right_v) => Ok(Field::Boolean($function(left_v, right_v))),
1✔
182
                    // left: Decimal, right: Null
183
                    Field::Null => Ok(Field::Boolean(false)),
1✔
184
                    _ => Err(PipelineError::InvalidOperandType($op.to_string())),
×
185
                },
186
                Field::String(left_v) => match right_p {
3,002✔
187
                    Field::String(right_v) => Ok(Field::Boolean($function(left_v, right_v))),
3,001✔
188
                    Field::Null => Ok(Field::Boolean(false)),
1✔
189
                    _ => Err(PipelineError::InvalidOperandType($op.to_string())),
×
190
                },
191
                Field::Timestamp(left_v) => match right_p {
×
192
                    Field::Timestamp(right_v) => Ok(Field::Boolean($function(left_v, right_v))),
×
193
                    Field::Null => Ok(Field::Boolean(false)),
×
194
                    _ => Err(PipelineError::InvalidOperandType($op.to_string())),
×
195
                },
196
                Field::Binary(_left_v) => Err(PipelineError::InvalidOperandType($op.to_string())),
×
197

198
                _ => Err(PipelineError::InvalidOperandType($op.to_string())),
×
199
            }
200
        }
15,064✔
201
    };
202
}
203

204
pub fn evaluate_lt(
2,020✔
205
    schema: &Schema,
2,020✔
206
    left: &Expression,
2,020✔
207
    right: &Expression,
2,020✔
208
    record: &Record,
2,020✔
209
) -> Result<Field, PipelineError> {
2,020✔
210
    let left_p = left.evaluate(record, schema)?;
2,020✔
211
    let right_p = right.evaluate(record, schema)?;
2,020✔
212

213
    match left_p {
2,020✔
214
        Field::Null => match right_p {
×
215
            Field::Null => Ok(Field::Boolean(true)),
×
216
            _ => Ok(Field::Boolean(false)),
×
217
        },
218
        Field::Boolean(left_v) => match right_p {
×
219
            Field::Boolean(right_v) => Ok(Field::Boolean(!left_v & right_v)),
×
220
            _ => Ok(Field::Boolean(false)),
×
221
        },
222
        Field::Int(left_v) => match right_p {
2,020✔
223
            Field::Int(right_v) => Ok(Field::Boolean(left_v < right_v)),
2,020✔
224
            Field::Float(right_v) => {
×
225
                let left_v_f = OrderedFloat::<f64>::from_i64(left_v).unwrap();
×
226
                Ok(Field::Boolean(left_v_f < right_v))
×
227
            }
228
            Field::Null => Ok(Field::Boolean(false)),
×
229
            _ => Err(PipelineError::InvalidOperandType("<".to_string())),
×
230
        },
231
        Field::Float(left_v) => match right_p {
×
232
            Field::Float(right_v) => Ok(Field::Boolean(left_v < right_v)),
×
233
            Field::Int(right_v) => {
×
234
                let right_v_f = OrderedFloat::<f64>::from_i64(right_v).unwrap();
×
235
                Ok(Field::Boolean(left_v < right_v_f))
×
236
            }
237
            Field::Null => Ok(Field::Boolean(false)),
×
238
            _ => Err(PipelineError::InvalidOperandType("<".to_string())),
×
239
        },
240
        Field::String(left_v) => match right_p {
×
241
            Field::String(right_v) => Ok(Field::Boolean(left_v < right_v)),
×
242
            Field::Null => Ok(Field::Boolean(false)),
×
243
            _ => Err(PipelineError::InvalidOperandType("<".to_string())),
×
244
        },
245
        Field::Timestamp(left_v) => match right_p {
×
246
            Field::Timestamp(right_v) => Ok(Field::Boolean(left_v < right_v)),
×
247
            Field::Null => Ok(Field::Boolean(false)),
×
248
            _ => Err(PipelineError::InvalidOperandType("<".to_string())),
×
249
        },
250
        Field::Binary(_left_v) => Err(PipelineError::InvalidOperandType("<".to_string())),
×
251
        _ => Err(PipelineError::InvalidOperandType("<".to_string())),
×
252
    }
253
}
2,020✔
254

255
pub fn evaluate_gt(
1,055✔
256
    schema: &Schema,
1,055✔
257
    left: &Expression,
1,055✔
258
    right: &Expression,
1,055✔
259
    record: &Record,
1,055✔
260
) -> Result<Field, PipelineError> {
1,055✔
261
    let left_p = left.evaluate(record, schema)?;
1,055✔
262
    let right_p = right.evaluate(record, schema)?;
1,055✔
263

264
    match left_p {
1,055✔
265
        Field::Null => match right_p {
×
266
            Field::Null => Ok(Field::Boolean(true)),
×
267
            _ => Ok(Field::Boolean(false)),
×
268
        },
269
        Field::Boolean(left_v) => match right_p {
×
270
            Field::Boolean(right_v) => Ok(Field::Boolean(left_v & !right_v)),
×
271
            _ => Ok(Field::Boolean(false)),
×
272
        },
273
        Field::Int(left_v) => match right_p {
1,055✔
274
            Field::Int(right_v) => Ok(Field::Boolean(left_v > right_v)),
1,055✔
275
            Field::Float(right_v) => {
×
276
                let left_v_f = OrderedFloat::<f64>::from_i64(left_v).unwrap();
×
277
                Ok(Field::Boolean(left_v_f > right_v))
×
278
            }
279
            Field::Null => Ok(Field::Boolean(false)),
×
280
            _ => Err(PipelineError::InvalidOperandType(">".to_string())),
×
281
        },
282
        Field::Float(left_v) => match right_p {
×
283
            Field::Float(right_v) => Ok(Field::Boolean(left_v > right_v)),
×
284
            Field::Int(right_v) => {
×
285
                let right_v_f = OrderedFloat::<f64>::from_i64(right_v).unwrap();
×
286
                Ok(Field::Boolean(left_v > right_v_f))
×
287
            }
288
            Field::Null => Ok(Field::Boolean(false)),
×
289
            _ => Err(PipelineError::InvalidOperandType(">".to_string())),
×
290
        },
291
        Field::String(left_v) => match right_p {
×
292
            Field::String(right_v) => Ok(Field::Boolean(left_v > right_v)),
×
293
            Field::Null => Ok(Field::Boolean(false)),
×
294
            _ => Err(PipelineError::InvalidOperandType(">".to_string())),
×
295
        },
296
        Field::Timestamp(left_v) => match right_p {
×
297
            Field::Timestamp(right_v) => Ok(Field::Boolean(left_v > right_v)),
×
298
            Field::Null => Ok(Field::Boolean(false)),
×
299
            _ => Err(PipelineError::InvalidOperandType(">".to_string())),
×
300
        },
301
        Field::Binary(_left_v) => Err(PipelineError::InvalidOperandType(">".to_string())),
×
302

303
        _ => Err(PipelineError::InvalidOperandType(">".to_string())),
×
304
    }
305
}
1,055✔
306

307
define_comparison!(evaluate_eq, "=", |l, r| { l == r });
3,009✔
308
define_comparison!(evaluate_ne, "!=", |l, r| { l != r });
×
309
define_comparison!(evaluate_lte, "<=", |l, r| { l <= r });
2,020✔
310
define_comparison!(evaluate_gte, ">=", |l, r| { l >= r });
10,000✔
311

312
#[cfg(test)]
313
use crate::pipeline::expression::execution::Expression::Literal;
314

315
#[test]
1✔
316
fn test_float_float_eq() {
1✔
317
    let row = Record::new(None, vec![], None);
1✔
318
    let f0 = Box::new(Literal(Field::Float(OrderedFloat(1.3))));
1✔
319
    let f1 = Box::new(Literal(Field::Float(OrderedFloat(1.3))));
1✔
320
    assert!(matches!(
1✔
321
        evaluate_eq(&Schema::empty(), &f0, &f1, &row),
1✔
322
        Ok(Field::Boolean(true))
323
    ));
324
}
1✔
325

326
#[test]
1✔
327
fn test_float_null_eq() {
1✔
328
    let row = Record::new(None, vec![], None);
1✔
329
    let f0 = Box::new(Literal(Field::Float(OrderedFloat(1.3))));
1✔
330
    let f1 = Box::new(Literal(Field::Null));
1✔
331
    assert!(matches!(
1✔
332
        evaluate_eq(&Schema::empty(), &f0, &f1, &row),
1✔
333
        Ok(Field::Boolean(false))
334
    ));
335
}
1✔
336

337
#[test]
1✔
338
fn test_float_int_eq() {
1✔
339
    let row = Record::new(None, vec![], None);
1✔
340
    let f0 = Box::new(Literal(Field::Float(OrderedFloat(1.0))));
1✔
341
    let f1 = Box::new(Literal(Field::Int(1)));
1✔
342
    assert!(matches!(
1✔
343
        evaluate_eq(&Schema::empty(), &f0, &f1, &row),
1✔
344
        Ok(Field::Boolean(true))
345
    ));
346
}
1✔
347

348
#[test]
1✔
349
fn test_decimal_decimal_eq() {
1✔
350
    let row = Record::new(None, vec![], None);
1✔
351
    let d0 = Box::new(Literal(Field::Decimal(Decimal::from_f64(1.3).unwrap())));
1✔
352
    let d1 = Box::new(Literal(Field::Decimal(Decimal::from_f64(1.3).unwrap())));
1✔
353
    assert!(matches!(
1✔
354
        evaluate_eq(&Schema::empty(), &d0, &d1, &row),
1✔
355
        Ok(Field::Boolean(true))
356
    ));
357
}
1✔
358

359
#[test]
1✔
360
fn test_decimal_null_eq() {
1✔
361
    let row = Record::new(None, vec![], None);
1✔
362
    let d0 = Box::new(Literal(Field::Decimal(Decimal::from_f64(1.3).unwrap())));
1✔
363
    let d1 = Box::new(Literal(Field::Null));
1✔
364
    assert!(matches!(
1✔
365
        evaluate_eq(&Schema::empty(), &d0, &d1, &row),
1✔
366
        Ok(Field::Boolean(false))
367
    ));
368
}
1✔
369

370
#[test]
1✔
371
fn test_decimal_int_eq() {
1✔
372
    let row = Record::new(None, vec![], None);
1✔
373
    let d0 = Box::new(Literal(Field::Decimal(Decimal::from_f64(1.0).unwrap())));
1✔
374
    let d1 = Box::new(Literal(Field::Int(1)));
1✔
375
    assert!(matches!(
1✔
376
        evaluate_eq(&Schema::empty(), &d0, &d1, &row),
1✔
377
        Ok(Field::Boolean(true))
378
    ));
379
}
1✔
380

381
#[test]
1✔
382
fn test_int_null_eq() {
1✔
383
    let row = Record::new(None, vec![], None);
1✔
384
    let f0 = Box::new(Literal(Field::Float(OrderedFloat(1.0))));
1✔
385
    let f1 = Box::new(Literal(Field::Null));
1✔
386
    assert!(matches!(
1✔
387
        evaluate_eq(&Schema::empty(), &f0, &f1, &row),
1✔
388
        Ok(Field::Boolean(false))
389
    ));
390
}
1✔
391

392
#[test]
1✔
393
fn test_int_float_eq() {
1✔
394
    let row = Record::new(None, vec![], None);
1✔
395
    let f0 = Box::new(Literal(Field::Int(1)));
1✔
396
    let f1 = Box::new(Literal(Field::Float(OrderedFloat(1.0))));
1✔
397
    assert!(matches!(
1✔
398
        evaluate_eq(&Schema::empty(), &f0, &f1, &row),
1✔
399
        Ok(Field::Boolean(true))
400
    ));
401
}
1✔
402

403
#[test]
1✔
404
fn test_uint_uint_eq() {
1✔
405
    let row = Record::new(None, vec![], None);
1✔
406
    let u0 = Box::new(Literal(Field::UInt(2)));
1✔
407
    let u1 = Box::new(Literal(Field::UInt(2)));
1✔
408
    assert!(matches!(
1✔
409
        evaluate_eq(&Schema::empty(), &u0, &u1, &row),
1✔
410
        Ok(Field::Boolean(true))
411
    ));
412
}
1✔
413

414
#[test]
1✔
415
fn test_uint_null_eq() {
1✔
416
    let row = Record::new(None, vec![], None);
1✔
417
    let u0 = Box::new(Literal(Field::UInt(2)));
1✔
418
    let u1 = Box::new(Literal(Field::Null));
1✔
419
    assert!(matches!(
1✔
420
        evaluate_eq(&Schema::empty(), &u0, &u1, &row),
1✔
421
        Ok(Field::Boolean(false))
422
    ));
423
}
1✔
424

425
#[test]
1✔
426
fn test_uint_decimal_eq() {
1✔
427
    let row = Record::new(None, vec![], None);
1✔
428
    let u0 = Box::new(Literal(Field::Decimal(Decimal::from_f64(2.0).unwrap())));
1✔
429
    let u1 = Box::new(Literal(Field::UInt(2)));
1✔
430
    assert!(matches!(
1✔
431
        evaluate_eq(&Schema::empty(), &u0, &u1, &row),
1✔
432
        Ok(Field::Boolean(true))
433
    ));
434
}
1✔
435

436
#[test]
1✔
437
fn test_bool_bool_eq() {
1✔
438
    let row = Record::new(None, vec![], None);
1✔
439
    let f0 = Box::new(Literal(Field::Boolean(false)));
1✔
440
    let f1 = Box::new(Literal(Field::Boolean(false)));
1✔
441
    assert!(matches!(
1✔
442
        evaluate_eq(&Schema::empty(), &f0, &f1, &row),
1✔
443
        Ok(Field::Boolean(true))
444
    ));
445
}
1✔
446

447
#[test]
1✔
448
fn test_str_str_eq() {
1✔
449
    let row = Record::new(None, vec![], None);
1✔
450
    let f0 = Box::new(Literal(Field::String("abc".to_string())));
1✔
451
    let f1 = Box::new(Literal(Field::String("abc".to_string())));
1✔
452
    assert!(matches!(
1✔
453
        evaluate_eq(&Schema::empty(), &f0, &f1, &row),
1✔
454
        Ok(Field::Boolean(true))
455
    ));
456
}
1✔
457

458
#[test]
1✔
459
fn test_str_null_eq() {
1✔
460
    let row = Record::new(None, vec![], None);
1✔
461
    let f0 = Box::new(Literal(Field::String("abc".to_string())));
1✔
462
    let f1 = Box::new(Literal(Field::Null));
1✔
463
    assert!(matches!(
1✔
464
        evaluate_eq(&Schema::empty(), &f0, &f1, &row),
1✔
465
        Ok(Field::Boolean(false))
466
    ));
467
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc