Coverage Report

Created: 2025-11-17 14:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/Users/andrewlamb/Software/arrow-rs/arrow-data/src/equal/mod.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
//! Module containing functionality to compute array equality.
19
//! This module uses [ArrayData] and does not
20
//! depend on dynamic casting of `Array`.
21
22
use crate::data::ArrayData;
23
use arrow_buffer::i256;
24
use arrow_schema::{DataType, IntervalUnit};
25
use half::f16;
26
27
mod boolean;
28
mod byte_view;
29
mod dictionary;
30
mod fixed_binary;
31
mod fixed_list;
32
mod list;
33
mod list_view;
34
mod null;
35
mod primitive;
36
mod run;
37
mod structure;
38
mod union;
39
mod utils;
40
mod variable_size;
41
42
// these methods assume the same type, len and null count.
43
// For this reason, they are not exposed and are instead used
44
// to build the generic functions below (`equal_range` and `equal`).
45
use self::run::run_equal;
46
use crate::equal::list_view::list_view_equal;
47
use boolean::boolean_equal;
48
use byte_view::byte_view_equal;
49
use dictionary::dictionary_equal;
50
use fixed_binary::fixed_binary_equal;
51
use fixed_list::fixed_list_equal;
52
use list::list_equal;
53
use null::null_equal;
54
use primitive::primitive_equal;
55
use structure::struct_equal;
56
use union::union_equal;
57
use variable_size::variable_sized_equal;
58
59
/// Compares the values of two [ArrayData] starting at `lhs_start` and `rhs_start` respectively
60
/// for `len` slots.
61
#[inline]
62
161k
fn equal_values(
63
161k
    lhs: &ArrayData,
64
161k
    rhs: &ArrayData,
65
161k
    lhs_start: usize,
66
161k
    rhs_start: usize,
67
161k
    len: usize,
68
161k
) -> bool {
69
161k
    match lhs.data_type() {
70
5
        DataType::Null => null_equal(lhs, rhs, lhs_start, rhs_start, len),
71
16
        DataType::Boolean => boolean_equal(lhs, rhs, lhs_start, rhs_start, len),
72
2
        DataType::UInt8 => primitive_equal::<u8>(lhs, rhs, lhs_start, rhs_start, len),
73
1
        DataType::UInt16 => primitive_equal::<u16>(lhs, rhs, lhs_start, rhs_start, len),
74
30
        DataType::UInt32 => primitive_equal::<u32>(lhs, rhs, lhs_start, rhs_start, len),
75
4
        DataType::UInt64 => primitive_equal::<u64>(lhs, rhs, lhs_start, rhs_start, len),
76
16
        DataType::Int8 => primitive_equal::<i8>(lhs, rhs, lhs_start, rhs_start, len),
77
5
        DataType::Int16 => primitive_equal::<i16>(lhs, rhs, lhs_start, rhs_start, len),
78
857
        DataType::Int32 => primitive_equal::<i32>(lhs, rhs, lhs_start, rhs_start, len),
79
71
        DataType::Int64 => primitive_equal::<i64>(lhs, rhs, lhs_start, rhs_start, len),
80
3
        DataType::Float32 => primitive_equal::<f32>(lhs, rhs, lhs_start, rhs_start, len),
81
4
        DataType::Float64 => primitive_equal::<f64>(lhs, rhs, lhs_start, rhs_start, len),
82
0
        DataType::Decimal32(_, _) => primitive_equal::<i32>(lhs, rhs, lhs_start, rhs_start, len),
83
0
        DataType::Decimal64(_, _) => primitive_equal::<i64>(lhs, rhs, lhs_start, rhs_start, len),
84
2
        DataType::Decimal128(_, _) => primitive_equal::<i128>(lhs, rhs, lhs_start, rhs_start, len),
85
0
        DataType::Decimal256(_, _) => primitive_equal::<i256>(lhs, rhs, lhs_start, rhs_start, len),
86
        DataType::Date32 | DataType::Time32(_) | DataType::Interval(IntervalUnit::YearMonth) => {
87
1
            primitive_equal::<i32>(lhs, rhs, lhs_start, rhs_start, len)
88
        }
89
        DataType::Date64
90
        | DataType::Interval(IntervalUnit::DayTime)
91
        | DataType::Time64(_)
92
        | DataType::Timestamp(_, _)
93
34
        | DataType::Duration(_) => primitive_equal::<i64>(lhs, rhs, lhs_start, rhs_start, len),
94
        DataType::Interval(IntervalUnit::MonthDayNano) => {
95
1
            primitive_equal::<i128>(lhs, rhs, lhs_start, rhs_start, len)
96
        }
97
        DataType::Utf8 | DataType::Binary => {
98
80.1k
            variable_sized_equal::<i32>(lhs, rhs, lhs_start, rhs_start, len)
99
        }
100
        DataType::LargeUtf8 | DataType::LargeBinary => {
101
3
            variable_sized_equal::<i64>(lhs, rhs, lhs_start, rhs_start, len)
102
        }
103
2
        DataType::FixedSizeBinary(_) => fixed_binary_equal(lhs, rhs, lhs_start, rhs_start, len),
104
        DataType::BinaryView | DataType::Utf8View => {
105
52
            byte_view_equal(lhs, rhs, lhs_start, rhs_start, len)
106
        }
107
8
        DataType::List(_) => list_equal::<i32>(lhs, rhs, lhs_start, rhs_start, len),
108
4
        DataType::LargeList(_) => list_equal::<i64>(lhs, rhs, lhs_start, rhs_start, len),
109
8
        DataType::ListView(_) => list_view_equal::<i32>(lhs, rhs, lhs_start, rhs_start, len),
110
6
        DataType::LargeListView(_) => list_view_equal::<i64>(lhs, rhs, lhs_start, rhs_start, len),
111
4
        DataType::FixedSizeList(_, _) => fixed_list_equal(lhs, rhs, lhs_start, rhs_start, len),
112
11
        DataType::Struct(_) => struct_equal(lhs, rhs, lhs_start, rhs_start, len),
113
5
        DataType::Union(_, _) => union_equal(lhs, rhs, lhs_start, rhs_start, len),
114
80.0k
        DataType::Dictionary(data_type, _) => match data_type.as_ref() {
115
1
            DataType::Int8 => dictionary_equal::<i8>(lhs, rhs, lhs_start, rhs_start, len),
116
0
            DataType::Int16 => dictionary_equal::<i16>(lhs, rhs, lhs_start, rhs_start, len),
117
80.0k
            DataType::Int32 => dictionary_equal::<i32>(lhs, rhs, lhs_start, rhs_start, len),
118
0
            DataType::Int64 => dictionary_equal::<i64>(lhs, rhs, lhs_start, rhs_start, len),
119
0
            DataType::UInt8 => dictionary_equal::<u8>(lhs, rhs, lhs_start, rhs_start, len),
120
0
            DataType::UInt16 => dictionary_equal::<u16>(lhs, rhs, lhs_start, rhs_start, len),
121
0
            DataType::UInt32 => dictionary_equal::<u32>(lhs, rhs, lhs_start, rhs_start, len),
122
0
            DataType::UInt64 => dictionary_equal::<u64>(lhs, rhs, lhs_start, rhs_start, len),
123
0
            _ => unreachable!(),
124
        },
125
0
        DataType::Float16 => primitive_equal::<f16>(lhs, rhs, lhs_start, rhs_start, len),
126
2
        DataType::Map(_, _) => list_equal::<i32>(lhs, rhs, lhs_start, rhs_start, len),
127
0
        DataType::RunEndEncoded(_, _) => run_equal(lhs, rhs, lhs_start, rhs_start, len),
128
    }
129
161k
}
130
131
80.1k
fn equal_range(
132
80.1k
    lhs: &ArrayData,
133
80.1k
    rhs: &ArrayData,
134
80.1k
    lhs_start: usize,
135
80.1k
    rhs_start: usize,
136
80.1k
    len: usize,
137
80.1k
) -> bool {
138
80.1k
    utils::equal_nulls(lhs, rhs, lhs_start, rhs_start, len)
139
80.1k
        && equal_values(lhs, rhs, lhs_start, rhs_start, len)
140
80.1k
}
141
142
/// Logically compares two [ArrayData].
143
///
144
/// Two arrays are logically equal if and only if:
145
/// * their data types are equal
146
/// * their lengths are equal
147
/// * their null counts are equal
148
/// * their null bitmaps are equal
149
/// * each of their items are equal
150
///
151
/// Two items are equal when their in-memory representation is physically equal
152
/// (i.e. has the same bit content).
153
///
154
/// The physical comparison depend on the data type.
155
///
156
/// # Panics
157
///
158
/// This function may panic whenever any of the [ArrayData] does not follow the
159
/// Arrow specification. (e.g. wrong number of buffers, buffer `len` does not
160
/// correspond to the declared `len`)
161
81.1k
pub fn equal(lhs: &ArrayData, rhs: &ArrayData) -> bool {
162
81.1k
    utils::base_equal(lhs, rhs)
163
81.1k
        && lhs.null_count() == rhs.null_count()
164
81.1k
        && utils::equal_nulls(lhs, rhs, 0, 0, lhs.len())
165
81.1k
        && equal_values(lhs, rhs, 0, 0, lhs.len())
166
81.1k
}
167
168
// See arrow/tests/array_equal.rs for tests