Skip to main content

arrow_data/equal/
fixed_binary.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: See the NOTICE file distributed with this work for additional information regarding copyright ownership
3// SPDX-FileContributor: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements
4
5use crate::bit_iterator::BitSliceIterator;
6use crate::contains_nulls;
7use crate::data::{ArrayData, get_fixed_size_binary_width};
8use crate::equal::primitive::NULL_SLICES_SELECTIVITY_THRESHOLD;
9
10use super::utils::equal_len;
11
12pub(super) fn fixed_binary_equal(
13    lhs: &ArrayData,
14    rhs: &ArrayData,
15    lhs_start: usize,
16    rhs_start: usize,
17    len: usize,
18) -> bool {
19    let size = get_fixed_size_binary_width(lhs.data_type());
20
21    let lhs_values = &lhs.buffers()[0].as_slice()[lhs.offset() * size..];
22    let rhs_values = &rhs.buffers()[0].as_slice()[rhs.offset() * size..];
23
24    // Only checking one null mask here because by the time the control flow reaches
25    // this point, the equality of the two masks would have already been verified.
26    if !contains_nulls(lhs.nulls(), lhs_start, len) {
27        equal_len(
28            lhs_values,
29            rhs_values,
30            size * lhs_start,
31            size * rhs_start,
32            size * len,
33        )
34    } else {
35        let selectivity_frac = lhs.null_count() as f64 / lhs.len() as f64;
36
37        // get a ref of the null buffer bytes, to use in testing for nullness
38        let lhs_nulls = lhs.nulls().unwrap();
39        let rhs_nulls = rhs.nulls().unwrap();
40
41        if selectivity_frac >= NULL_SLICES_SELECTIVITY_THRESHOLD {
42            // with nulls, we need to compare item by item whenever it is not null
43            (0..len).all(|i| {
44                let lhs_pos = lhs_start + i;
45                let rhs_pos = rhs_start + i;
46
47                let lhs_is_null = lhs_nulls.is_null(lhs_pos);
48                let rhs_is_null = rhs_nulls.is_null(rhs_pos);
49
50                lhs_is_null
51                    || (lhs_is_null == rhs_is_null)
52                        && equal_len(
53                            lhs_values,
54                            rhs_values,
55                            lhs_pos * size,
56                            rhs_pos * size,
57                            size, // 1 * size since we are comparing a single entry
58                        )
59            })
60        } else {
61            let lhs_slices_iter =
62                BitSliceIterator::new(lhs_nulls.validity(), lhs_start + lhs_nulls.offset(), len);
63            let rhs_slices_iter =
64                BitSliceIterator::new(rhs_nulls.validity(), rhs_start + rhs_nulls.offset(), len);
65
66            lhs_slices_iter
67                .zip(rhs_slices_iter)
68                .all(|((l_start, l_end), (r_start, r_end))| {
69                    l_start == r_start
70                        && l_end == r_end
71                        && equal_len(
72                            lhs_values,
73                            rhs_values,
74                            (lhs_start + l_start) * size,
75                            (rhs_start + r_start) * size,
76                            (l_end - l_start) * size,
77                        )
78                })
79        }
80    }
81}