Coverage Report

Created: 2025-08-26 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/Users/andrewlamb/Software/arrow-rs/arrow-arith/src/boolean.rs
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
//! Defines boolean kernels on Arrow `BooleanArray`'s, e.g. `AND`, `OR` and `NOT`.
19
//!
20
//! These kernels can leverage SIMD if available on your system.  Currently no runtime
21
//! detection is provided, you should enable the specific SIMD intrinsics using
22
//! `RUSTFLAGS="-C target-feature=+avx2"` for example.  See the documentation
23
//! [here](https://doc.rust-lang.org/stable/core/arch/) for more information.
24
25
use arrow_array::*;
26
use arrow_buffer::buffer::{bitwise_bin_op_helper, bitwise_quaternary_op_helper};
27
use arrow_buffer::{buffer_bin_and_not, BooleanBuffer, NullBuffer};
28
use arrow_schema::ArrowError;
29
30
/// Logical 'and' boolean values with Kleene logic
31
///
32
/// # Behavior
33
///
34
/// This function behaves as follows with nulls:
35
///
36
/// * `true` and `null` = `null`
37
/// * `null` and `true` = `null`
38
/// * `false` and `null` = `false`
39
/// * `null` and `false` = `false`
40
/// * `null` and `null` = `null`
41
///
42
/// In other words, in this context a null value really means \"unknown\",
43
/// and an unknown value 'and' false is always false.
44
/// For a different null behavior, see function \"and\".
45
///
46
/// # Example
47
///
48
/// ```rust
49
/// # use arrow_array::BooleanArray;
50
/// # use arrow_arith::boolean::and_kleene;
51
/// let a = BooleanArray::from(vec![Some(true), Some(false), None]);
52
/// let b = BooleanArray::from(vec![None, None, None]);
53
/// let and_ab = and_kleene(&a, &b).unwrap();
54
/// assert_eq!(and_ab, BooleanArray::from(vec![None, Some(false), None]));
55
/// ```
56
///
57
/// # Fails
58
///
59
/// If the operands have different lengths
60
pub fn and_kleene(left: &BooleanArray, right: &BooleanArray) -> Result<BooleanArray, ArrowError> {
61
    if left.len() != right.len() {
62
        return Err(ArrowError::ComputeError(
63
            "Cannot perform bitwise operation on arrays of different length".to_string(),
64
        ));
65
    }
66
67
    let left_values = left.values();
68
    let right_values = right.values();
69
70
    let buffer = match (left.nulls(), right.nulls()) {
71
        (None, None) => None,
72
        (Some(left_null_buffer), None) => {
73
            // The right side has no null values.
74
            // The final null bit is set only if:
75
            // 1. left null bit is set, or
76
            // 2. right data bit is false (because null AND false = false).
77
            Some(bitwise_bin_op_helper(
78
                left_null_buffer.buffer(),
79
                left_null_buffer.offset(),
80
                right_values.inner(),
81
                right_values.offset(),
82
                left.len(),
83
0
                |a, b| a | !b,
84
            ))
85
        }
86
        (None, Some(right_null_buffer)) => {
87
            // Same as above
88
            Some(bitwise_bin_op_helper(
89
                right_null_buffer.buffer(),
90
                right_null_buffer.offset(),
91
                left_values.inner(),
92
                left_values.offset(),
93
                left.len(),
94
0
                |a, b| a | !b,
95
            ))
96
        }
97
        (Some(left_null_buffer), Some(right_null_buffer)) => {
98
            // Follow the same logic above. Both sides have null values.
99
            // Assume a is left null bits, b is left data bits, c is right null bits,
100
            // d is right data bits.
101
            // The final null bits are:
102
            // (a | (c & !d)) & (c | (a & !b))
103
            Some(bitwise_quaternary_op_helper(
104
                [
105
                    left_null_buffer.buffer(),
106
                    left_values.inner(),
107
                    right_null_buffer.buffer(),
108
                    right_values.inner(),
109
                ],
110
                [
111
                    left_null_buffer.offset(),
112
                    left_values.offset(),
113
                    right_null_buffer.offset(),
114
                    right_values.offset(),
115
                ],
116
                left.len(),
117
0
                |a, b, c, d| (a | (c & !d)) & (c | (a & !b)),
118
            ))
119
        }
120
    };
121
0
    let nulls = buffer.map(|b| NullBuffer::new(BooleanBuffer::new(b, 0, left.len())));
122
    Ok(BooleanArray::new(left_values & right_values, nulls))
123
}
124
125
/// Logical 'or' boolean values with Kleene logic
126
///
127
/// # Behavior
128
///
129
/// This function behaves as follows with nulls:
130
///
131
/// * `true` or `null` = `true`
132
/// * `null` or `true` = `true`
133
/// * `false` or `null` = `null`
134
/// * `null` or `false` = `null`
135
/// * `null` or `null` = `null`
136
///
137
/// In other words, in this context a null value really means \"unknown\",
138
/// and an unknown value 'or' true is always true.
139
/// For a different null behavior, see function \"or\".
140
///
141
/// # Example
142
///
143
/// ```rust
144
/// # use arrow_array::BooleanArray;
145
/// # use arrow_arith::boolean::or_kleene;
146
/// let a = BooleanArray::from(vec![Some(true), Some(false), None]);
147
/// let b = BooleanArray::from(vec![None, None, None]);
148
/// let or_ab = or_kleene(&a, &b).unwrap();
149
/// assert_eq!(or_ab, BooleanArray::from(vec![Some(true), None, None]));
150
/// ```
151
///
152
/// # Fails
153
///
154
/// If the operands have different lengths
155
pub fn or_kleene(left: &BooleanArray, right: &BooleanArray) -> Result<BooleanArray, ArrowError> {
156
    if left.len() != right.len() {
157
        return Err(ArrowError::ComputeError(
158
            "Cannot perform bitwise operation on arrays of different length".to_string(),
159
        ));
160
    }
161
162
    let left_values = left.values();
163
    let right_values = right.values();
164
165
    let buffer = match (left.nulls(), right.nulls()) {
166
        (None, None) => None,
167
        (Some(left_nulls), None) => {
168
            // The right side has no null values.
169
            // The final null bit is set only if:
170
            // 1. left null bit is set, or
171
            // 2. right data bit is true (because null OR true = true).
172
            Some(bitwise_bin_op_helper(
173
                left_nulls.buffer(),
174
                left_nulls.offset(),
175
                right_values.inner(),
176
                right_values.offset(),
177
                left.len(),
178
0
                |a, b| a | b,
179
            ))
180
        }
181
        (None, Some(right_nulls)) => {
182
            // Same as above
183
            Some(bitwise_bin_op_helper(
184
                right_nulls.buffer(),
185
                right_nulls.offset(),
186
                left_values.inner(),
187
                left_values.offset(),
188
                left.len(),
189
0
                |a, b| a | b,
190
            ))
191
        }
192
        (Some(left_nulls), Some(right_nulls)) => {
193
            // Follow the same logic above. Both sides have null values.
194
            // Assume a is left null bits, b is left data bits, c is right null bits,
195
            // d is right data bits.
196
            // The final null bits are:
197
            // (a | (c & d)) & (c | (a & b))
198
            Some(bitwise_quaternary_op_helper(
199
                [
200
                    left_nulls.buffer(),
201
                    left_values.inner(),
202
                    right_nulls.buffer(),
203
                    right_values.inner(),
204
                ],
205
                [
206
                    left_nulls.offset(),
207
                    left_values.offset(),
208
                    right_nulls.offset(),
209
                    right_values.offset(),
210
                ],
211
                left.len(),
212
0
                |a, b, c, d| (a | (c & d)) & (c | (a & b)),
213
            ))
214
        }
215
    };
216
217
0
    let nulls = buffer.map(|b| NullBuffer::new(BooleanBuffer::new(b, 0, left.len())));
218
    Ok(BooleanArray::new(left_values | right_values, nulls))
219
}
220
221
/// Helper function to implement binary kernels
222
0
pub(crate) fn binary_boolean_kernel<F>(
223
0
    left: &BooleanArray,
224
0
    right: &BooleanArray,
225
0
    op: F,
226
0
) -> Result<BooleanArray, ArrowError>
227
0
where
228
0
    F: Fn(&BooleanBuffer, &BooleanBuffer) -> BooleanBuffer,
229
{
230
0
    if left.len() != right.len() {
231
0
        return Err(ArrowError::ComputeError(
232
0
            "Cannot perform bitwise operation on arrays of different length".to_string(),
233
0
        ));
234
0
    }
235
236
0
    let nulls = NullBuffer::union(left.nulls(), right.nulls());
237
0
    let values = op(left.values(), right.values());
238
0
    Ok(BooleanArray::new(values, nulls))
239
0
}
240
241
/// Performs `AND` operation on two arrays. If either left or right value is null then the
242
/// result is also null.
243
/// # Error
244
/// This function errors when the arrays have different lengths.
245
/// # Example
246
/// ```rust
247
/// # use arrow_array::BooleanArray;
248
/// # use arrow_arith::boolean::and;
249
/// let a = BooleanArray::from(vec![Some(false), Some(true), None]);
250
/// let b = BooleanArray::from(vec![Some(true), Some(true), Some(false)]);
251
/// let and_ab = and(&a, &b).unwrap();
252
/// assert_eq!(and_ab, BooleanArray::from(vec![Some(false), Some(true), None]));
253
/// ```
254
pub fn and(left: &BooleanArray, right: &BooleanArray) -> Result<BooleanArray, ArrowError> {
255
0
    binary_boolean_kernel(left, right, |a, b| a & b)
256
}
257
258
/// Performs `OR` operation on two arrays. If either left or right value is null then the
259
/// result is also null.
260
/// # Error
261
/// This function errors when the arrays have different lengths.
262
/// # Example
263
/// ```rust
264
/// # use arrow_array::BooleanArray;
265
/// # use arrow_arith::boolean::or;
266
/// let a = BooleanArray::from(vec![Some(false), Some(true), None]);
267
/// let b = BooleanArray::from(vec![Some(true), Some(true), Some(false)]);
268
/// let or_ab = or(&a, &b).unwrap();
269
/// assert_eq!(or_ab, BooleanArray::from(vec![Some(true), Some(true), None]));
270
/// ```
271
pub fn or(left: &BooleanArray, right: &BooleanArray) -> Result<BooleanArray, ArrowError> {
272
0
    binary_boolean_kernel(left, right, |a, b| a | b)
273
}
274
275
/// Performs `AND_NOT` operation on two arrays. If either left or right value is null then the
276
/// result is also null.
277
/// # Error
278
/// This function errors when the arrays have different lengths.
279
/// # Example
280
/// ```rust
281
/// # use arrow_array::BooleanArray;
282
/// # use arrow_arith::boolean::{and, not, and_not};
283
/// let a = BooleanArray::from(vec![Some(false), Some(true), None]);
284
/// let b = BooleanArray::from(vec![Some(true), Some(true), Some(false)]);
285
/// let andn_ab = and_not(&a, &b).unwrap();
286
/// assert_eq!(andn_ab, BooleanArray::from(vec![Some(false), Some(false), None]));
287
/// // It's equal to and(left, not(right))
288
/// assert_eq!(andn_ab, and(&a, &not(&b).unwrap()).unwrap());
289
pub fn and_not(left: &BooleanArray, right: &BooleanArray) -> Result<BooleanArray, ArrowError> {
290
0
    binary_boolean_kernel(left, right, |a, b| {
291
0
        let buffer = buffer_bin_and_not(a.inner(), b.offset(), b.inner(), a.offset(), a.len());
292
0
        BooleanBuffer::new(buffer, left.offset(), left.len())
293
0
    })
294
}
295
296
/// Performs unary `NOT` operation on an arrays. If value is null then the result is also
297
/// null.
298
/// # Error
299
/// This function never errors. It returns an error for consistency.
300
/// # Example
301
/// ```rust
302
/// # use arrow_array::BooleanArray;
303
/// # use arrow_arith::boolean::not;
304
/// let a = BooleanArray::from(vec![Some(false), Some(true), None]);
305
/// let not_a = not(&a).unwrap();
306
/// assert_eq!(not_a, BooleanArray::from(vec![Some(true), Some(false), None]));
307
/// ```
308
pub fn not(left: &BooleanArray) -> Result<BooleanArray, ArrowError> {
309
    let nulls = left.nulls().cloned();
310
    let values = !left.values();
311
    Ok(BooleanArray::new(values, nulls))
312
}
313
314
/// Returns a non-null [BooleanArray] with whether each value of the array is null.
315
/// # Error
316
/// This function never errors.
317
/// # Example
318
/// ```rust
319
/// # use arrow_array::BooleanArray;
320
/// # use arrow_arith::boolean::is_null;
321
/// let a = BooleanArray::from(vec![Some(false), Some(true), None]);
322
/// let a_is_null = is_null(&a).unwrap();
323
/// assert_eq!(a_is_null, BooleanArray::from(vec![false, false, true]));
324
/// ```
325
pub fn is_null(input: &dyn Array) -> Result<BooleanArray, ArrowError> {
326
    let values = match input.logical_nulls() {
327
        None => BooleanBuffer::new_unset(input.len()),
328
        Some(nulls) => !nulls.inner(),
329
    };
330
331
    Ok(BooleanArray::new(values, None))
332
}
333
334
/// Returns a non-null [BooleanArray] with whether each value of the array is not null.
335
/// # Error
336
/// This function never errors.
337
/// # Example
338
/// ```rust
339
/// # use arrow_array::BooleanArray;
340
/// # use arrow_arith::boolean::is_not_null;
341
/// let a = BooleanArray::from(vec![Some(false), Some(true), None]);
342
/// let a_is_not_null = is_not_null(&a).unwrap();
343
/// assert_eq!(a_is_not_null, BooleanArray::from(vec![true, true, false]));
344
/// ```
345
pub fn is_not_null(input: &dyn Array) -> Result<BooleanArray, ArrowError> {
346
    let values = match input.logical_nulls() {
347
        None => BooleanBuffer::new_set(input.len()),
348
        Some(n) => n.inner().clone(),
349
    };
350
    Ok(BooleanArray::new(values, None))
351
}
352
353
#[cfg(test)]
354
mod tests {
355
    use arrow_buffer::ScalarBuffer;
356
    use arrow_schema::{DataType, Field, UnionFields};
357
358
    use super::*;
359
    use std::sync::Arc;
360
361
    #[test]
362
    fn test_bool_array_and() {
363
        let a = BooleanArray::from(vec![false, false, true, true]);
364
        let b = BooleanArray::from(vec![false, true, false, true]);
365
        let c = and(&a, &b).unwrap();
366
367
        let expected = BooleanArray::from(vec![false, false, false, true]);
368
369
        assert_eq!(c, expected);
370
    }
371
372
    #[test]
373
    fn test_bool_array_or() {
374
        let a = BooleanArray::from(vec![false, false, true, true]);
375
        let b = BooleanArray::from(vec![false, true, false, true]);
376
        let c = or(&a, &b).unwrap();
377
378
        let expected = BooleanArray::from(vec![false, true, true, true]);
379
380
        assert_eq!(c, expected);
381
    }
382
383
    #[test]
384
    fn test_bool_array_and_not() {
385
        let a = BooleanArray::from(vec![false, false, true, true]);
386
        let b = BooleanArray::from(vec![false, true, false, true]);
387
        let c = and_not(&a, &b).unwrap();
388
389
        let expected = BooleanArray::from(vec![false, false, true, false]);
390
391
        assert_eq!(c, expected);
392
        assert_eq!(c, and(&a, &not(&b).unwrap()).unwrap());
393
    }
394
395
    #[test]
396
    fn test_bool_array_or_nulls() {
397
        let a = BooleanArray::from(vec![
398
            None,
399
            None,
400
            None,
401
            Some(false),
402
            Some(false),
403
            Some(false),
404
            Some(true),
405
            Some(true),
406
            Some(true),
407
        ]);
408
        let b = BooleanArray::from(vec![
409
            None,
410
            Some(false),
411
            Some(true),
412
            None,
413
            Some(false),
414
            Some(true),
415
            None,
416
            Some(false),
417
            Some(true),
418
        ]);
419
        let c = or(&a, &b).unwrap();
420
421
        let expected = BooleanArray::from(vec![
422
            None,
423
            None,
424
            None,
425
            None,
426
            Some(false),
427
            Some(true),
428
            None,
429
            Some(true),
430
            Some(true),
431
        ]);
432
433
        assert_eq!(c, expected);
434
    }
435
436
    #[test]
437
    fn test_boolean_array_kleene_no_remainder() {
438
        let n = 1024;
439
        let a = BooleanArray::from(vec![true; n]);
440
        let b = BooleanArray::from(vec![None; n]);
441
        let result = or_kleene(&a, &b).unwrap();
442
443
        assert_eq!(result, a);
444
    }
445
446
    #[test]
447
    fn test_bool_array_and_kleene_nulls() {
448
        let a = BooleanArray::from(vec![
449
            None,
450
            None,
451
            None,
452
            Some(false),
453
            Some(false),
454
            Some(false),
455
            Some(true),
456
            Some(true),
457
            Some(true),
458
        ]);
459
        let b = BooleanArray::from(vec![
460
            None,
461
            Some(false),
462
            Some(true),
463
            None,
464
            Some(false),
465
            Some(true),
466
            None,
467
            Some(false),
468
            Some(true),
469
        ]);
470
        let c = and_kleene(&a, &b).unwrap();
471
472
        let expected = BooleanArray::from(vec![
473
            None,
474
            Some(false),
475
            None,
476
            Some(false),
477
            Some(false),
478
            Some(false),
479
            None,
480
            Some(false),
481
            Some(true),
482
        ]);
483
484
        assert_eq!(c, expected);
485
    }
486
487
    #[test]
488
    fn test_bool_array_or_kleene_nulls() {
489
        let a = BooleanArray::from(vec![
490
            None,
491
            None,
492
            None,
493
            Some(false),
494
            Some(false),
495
            Some(false),
496
            Some(true),
497
            Some(true),
498
            Some(true),
499
        ]);
500
        let b = BooleanArray::from(vec![
501
            None,
502
            Some(false),
503
            Some(true),
504
            None,
505
            Some(false),
506
            Some(true),
507
            None,
508
            Some(false),
509
            Some(true),
510
        ]);
511
        let c = or_kleene(&a, &b).unwrap();
512
513
        let expected = BooleanArray::from(vec![
514
            None,
515
            None,
516
            Some(true),
517
            None,
518
            Some(false),
519
            Some(true),
520
            Some(true),
521
            Some(true),
522
            Some(true),
523
        ]);
524
525
        assert_eq!(c, expected);
526
    }
527
528
    #[test]
529
    fn test_bool_array_or_kleene_right_sided_nulls() {
530
        let a = BooleanArray::from(vec![false, false, false, true, true, true]);
531
532
        // ensure null bitmap of a is absent
533
        assert!(a.nulls().is_none());
534
535
        let b = BooleanArray::from(vec![
536
            Some(true),
537
            Some(false),
538
            None,
539
            Some(true),
540
            Some(false),
541
            None,
542
        ]);
543
544
        // ensure null bitmap of b is present
545
        assert!(b.nulls().is_some());
546
547
        let c = or_kleene(&a, &b).unwrap();
548
549
        let expected = BooleanArray::from(vec![
550
            Some(true),
551
            Some(false),
552
            None,
553
            Some(true),
554
            Some(true),
555
            Some(true),
556
        ]);
557
558
        assert_eq!(c, expected);
559
    }
560
561
    #[test]
562
    fn test_bool_array_or_kleene_left_sided_nulls() {
563
        let a = BooleanArray::from(vec![
564
            Some(true),
565
            Some(false),
566
            None,
567
            Some(true),
568
            Some(false),
569
            None,
570
        ]);
571
572
        // ensure null bitmap of b is absent
573
        assert!(a.nulls().is_some());
574
575
        let b = BooleanArray::from(vec![false, false, false, true, true, true]);
576
577
        // ensure null bitmap of a is present
578
        assert!(b.nulls().is_none());
579
580
        let c = or_kleene(&a, &b).unwrap();
581
582
        let expected = BooleanArray::from(vec![
583
            Some(true),
584
            Some(false),
585
            None,
586
            Some(true),
587
            Some(true),
588
            Some(true),
589
        ]);
590
591
        assert_eq!(c, expected);
592
    }
593
594
    #[test]
595
    fn test_bool_array_not() {
596
        let a = BooleanArray::from(vec![false, true]);
597
        let c = not(&a).unwrap();
598
599
        let expected = BooleanArray::from(vec![true, false]);
600
601
        assert_eq!(c, expected);
602
    }
603
604
    #[test]
605
    fn test_bool_array_not_sliced() {
606
        let a = BooleanArray::from(vec![None, Some(true), Some(false), None, Some(true)]);
607
        let a = a.slice(1, 4);
608
        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
609
        let c = not(a).unwrap();
610
611
        let expected = BooleanArray::from(vec![Some(false), Some(true), None, Some(false)]);
612
613
        assert_eq!(c, expected);
614
    }
615
616
    #[test]
617
    fn test_bool_array_and_nulls() {
618
        let a = BooleanArray::from(vec![
619
            None,
620
            None,
621
            None,
622
            Some(false),
623
            Some(false),
624
            Some(false),
625
            Some(true),
626
            Some(true),
627
            Some(true),
628
        ]);
629
        let b = BooleanArray::from(vec![
630
            None,
631
            Some(false),
632
            Some(true),
633
            None,
634
            Some(false),
635
            Some(true),
636
            None,
637
            Some(false),
638
            Some(true),
639
        ]);
640
        let c = and(&a, &b).unwrap();
641
642
        let expected = BooleanArray::from(vec![
643
            None,
644
            None,
645
            None,
646
            None,
647
            Some(false),
648
            Some(false),
649
            None,
650
            Some(false),
651
            Some(true),
652
        ]);
653
654
        assert_eq!(c, expected);
655
    }
656
657
    #[test]
658
    fn test_bool_array_and_sliced_same_offset() {
659
        let a = BooleanArray::from(vec![
660
            false, false, false, false, false, false, false, false, false, false, true, true,
661
        ]);
662
        let b = BooleanArray::from(vec![
663
            false, false, false, false, false, false, false, false, false, true, false, true,
664
        ]);
665
666
        let a = a.slice(8, 4);
667
        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
668
        let b = b.slice(8, 4);
669
        let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
670
671
        let c = and(a, b).unwrap();
672
673
        let expected = BooleanArray::from(vec![false, false, false, true]);
674
675
        assert_eq!(expected, c);
676
    }
677
678
    #[test]
679
    fn test_bool_array_and_sliced_same_offset_mod8() {
680
        let a = BooleanArray::from(vec![
681
            false, false, true, true, false, false, false, false, false, false, false, false,
682
        ]);
683
        let b = BooleanArray::from(vec![
684
            false, false, false, false, false, false, false, false, false, true, false, true,
685
        ]);
686
687
        let a = a.slice(0, 4);
688
        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
689
        let b = b.slice(8, 4);
690
        let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
691
692
        let c = and(a, b).unwrap();
693
694
        let expected = BooleanArray::from(vec![false, false, false, true]);
695
696
        assert_eq!(expected, c);
697
    }
698
699
    #[test]
700
    fn test_bool_array_and_sliced_offset1() {
701
        let a = BooleanArray::from(vec![
702
            false, false, false, false, false, false, false, false, false, false, true, true,
703
        ]);
704
        let b = BooleanArray::from(vec![false, true, false, true]);
705
706
        let a = a.slice(8, 4);
707
        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
708
709
        let c = and(a, &b).unwrap();
710
711
        let expected = BooleanArray::from(vec![false, false, false, true]);
712
713
        assert_eq!(expected, c);
714
    }
715
716
    #[test]
717
    fn test_bool_array_and_sliced_offset2() {
718
        let a = BooleanArray::from(vec![false, false, true, true]);
719
        let b = BooleanArray::from(vec![
720
            false, false, false, false, false, false, false, false, false, true, false, true,
721
        ]);
722
723
        let b = b.slice(8, 4);
724
        let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
725
726
        let c = and(&a, b).unwrap();
727
728
        let expected = BooleanArray::from(vec![false, false, false, true]);
729
730
        assert_eq!(expected, c);
731
    }
732
733
    #[test]
734
    fn test_bool_array_and_nulls_offset() {
735
        let a = BooleanArray::from(vec![None, Some(false), Some(true), None, Some(true)]);
736
        let a = a.slice(1, 4);
737
        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
738
739
        let b = BooleanArray::from(vec![
740
            None,
741
            None,
742
            Some(true),
743
            Some(false),
744
            Some(true),
745
            Some(true),
746
        ]);
747
748
        let b = b.slice(2, 4);
749
        let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
750
751
        let c = and(a, b).unwrap();
752
753
        let expected = BooleanArray::from(vec![Some(false), Some(false), None, Some(true)]);
754
755
        assert_eq!(expected, c);
756
    }
757
758
    #[test]
759
    fn test_nonnull_array_is_null() {
760
        let a: ArrayRef = Arc::new(Int32Array::from(vec![1, 2, 3, 4]));
761
762
        let res = is_null(a.as_ref()).unwrap();
763
764
        let expected = BooleanArray::from(vec![false, false, false, false]);
765
766
        assert_eq!(expected, res);
767
        assert!(res.nulls().is_none());
768
    }
769
770
    #[test]
771
    fn test_nonnull_array_with_offset_is_null() {
772
        let a = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1]);
773
        let a = a.slice(8, 4);
774
775
        let res = is_null(&a).unwrap();
776
777
        let expected = BooleanArray::from(vec![false, false, false, false]);
778
779
        assert_eq!(expected, res);
780
        assert!(res.nulls().is_none());
781
    }
782
783
    #[test]
784
    fn test_nonnull_array_is_not_null() {
785
        let a = Int32Array::from(vec![1, 2, 3, 4]);
786
787
        let res = is_not_null(&a).unwrap();
788
789
        let expected = BooleanArray::from(vec![true, true, true, true]);
790
791
        assert_eq!(expected, res);
792
        assert!(res.nulls().is_none());
793
    }
794
795
    #[test]
796
    fn test_nonnull_array_with_offset_is_not_null() {
797
        let a = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1]);
798
        let a = a.slice(8, 4);
799
800
        let res = is_not_null(&a).unwrap();
801
802
        let expected = BooleanArray::from(vec![true, true, true, true]);
803
804
        assert_eq!(expected, res);
805
        assert!(res.nulls().is_none());
806
    }
807
808
    #[test]
809
    fn test_nullable_array_is_null() {
810
        let a = Int32Array::from(vec![Some(1), None, Some(3), None]);
811
812
        let res = is_null(&a).unwrap();
813
814
        let expected = BooleanArray::from(vec![false, true, false, true]);
815
816
        assert_eq!(expected, res);
817
        assert!(res.nulls().is_none());
818
    }
819
820
    #[test]
821
    fn test_nullable_array_with_offset_is_null() {
822
        let a = Int32Array::from(vec![
823
            None,
824
            None,
825
            None,
826
            None,
827
            None,
828
            None,
829
            None,
830
            None,
831
            // offset 8, previous None values are skipped by the slice
832
            Some(1),
833
            None,
834
            Some(2),
835
            None,
836
            Some(3),
837
            Some(4),
838
            None,
839
            None,
840
        ]);
841
        let a = a.slice(8, 4);
842
843
        let res = is_null(&a).unwrap();
844
845
        let expected = BooleanArray::from(vec![false, true, false, true]);
846
847
        assert_eq!(expected, res);
848
        assert!(res.nulls().is_none());
849
    }
850
851
    #[test]
852
    fn test_nullable_array_is_not_null() {
853
        let a = Int32Array::from(vec![Some(1), None, Some(3), None]);
854
855
        let res = is_not_null(&a).unwrap();
856
857
        let expected = BooleanArray::from(vec![true, false, true, false]);
858
859
        assert_eq!(expected, res);
860
        assert!(res.nulls().is_none());
861
    }
862
863
    #[test]
864
    fn test_nullable_array_with_offset_is_not_null() {
865
        let a = Int32Array::from(vec![
866
            None,
867
            None,
868
            None,
869
            None,
870
            None,
871
            None,
872
            None,
873
            None,
874
            // offset 8, previous None values are skipped by the slice
875
            Some(1),
876
            None,
877
            Some(2),
878
            None,
879
            Some(3),
880
            Some(4),
881
            None,
882
            None,
883
        ]);
884
        let a = a.slice(8, 4);
885
886
        let res = is_not_null(&a).unwrap();
887
888
        let expected = BooleanArray::from(vec![true, false, true, false]);
889
890
        assert_eq!(expected, res);
891
        assert!(res.nulls().is_none());
892
    }
893
894
    #[test]
895
    fn test_null_array_is_null() {
896
        let a = NullArray::new(3);
897
898
        let res = is_null(&a).unwrap();
899
900
        let expected = BooleanArray::from(vec![true, true, true]);
901
902
        assert_eq!(expected, res);
903
        assert!(res.nulls().is_none());
904
    }
905
906
    #[test]
907
    fn test_null_array_is_not_null() {
908
        let a = NullArray::new(3);
909
910
        let res = is_not_null(&a).unwrap();
911
912
        let expected = BooleanArray::from(vec![false, false, false]);
913
914
        assert_eq!(expected, res);
915
        assert!(res.nulls().is_none());
916
    }
917
918
    #[test]
919
    fn test_dense_union_is_null() {
920
        // union of [{A=1}, {A=}, {B=3.2}, {B=}, {C="a"}, {C=}]
921
        let int_array = Int32Array::from(vec![Some(1), None]);
922
        let float_array = Float64Array::from(vec![Some(3.2), None]);
923
        let str_array = StringArray::from(vec![Some("a"), None]);
924
        let type_ids = [0, 0, 1, 1, 2, 2].into_iter().collect::<ScalarBuffer<i8>>();
925
        let offsets = [0, 1, 0, 1, 0, 1]
926
            .into_iter()
927
            .collect::<ScalarBuffer<i32>>();
928
929
        let children = vec![
930
            Arc::new(int_array) as Arc<dyn Array>,
931
            Arc::new(float_array),
932
            Arc::new(str_array),
933
        ];
934
935
        let array = UnionArray::try_new(union_fields(), type_ids, Some(offsets), children).unwrap();
936
937
        let result = is_null(&array).unwrap();
938
939
        let expected = &BooleanArray::from(vec![false, true, false, true, false, true]);
940
        assert_eq!(expected, &result);
941
    }
942
943
    #[test]
944
    fn test_sparse_union_is_null() {
945
        // union of [{A=1}, {A=}, {B=3.2}, {B=}, {C="a"}, {C=}]
946
        let int_array = Int32Array::from(vec![Some(1), None, None, None, None, None]);
947
        let float_array = Float64Array::from(vec![None, None, Some(3.2), None, None, None]);
948
        let str_array = StringArray::from(vec![None, None, None, None, Some("a"), None]);
949
        let type_ids = [0, 0, 1, 1, 2, 2].into_iter().collect::<ScalarBuffer<i8>>();
950
951
        let children = vec![
952
            Arc::new(int_array) as Arc<dyn Array>,
953
            Arc::new(float_array),
954
            Arc::new(str_array),
955
        ];
956
957
        let array = UnionArray::try_new(union_fields(), type_ids, None, children).unwrap();
958
959
        let result = is_null(&array).unwrap();
960
961
        let expected = &BooleanArray::from(vec![false, true, false, true, false, true]);
962
        assert_eq!(expected, &result);
963
    }
964
965
    fn union_fields() -> UnionFields {
966
        [
967
            (0, Arc::new(Field::new("A", DataType::Int32, true))),
968
            (1, Arc::new(Field::new("B", DataType::Float64, true))),
969
            (2, Arc::new(Field::new("C", DataType::Utf8, true))),
970
        ]
971
        .into_iter()
972
        .collect()
973
    }
974
}