arrow_data/equal/
union.rs1use crate::data::ArrayData;
19use arrow_schema::{DataType, UnionFields, UnionMode};
20
21use super::equal_range;
22
23#[expect(clippy::too_many_arguments)]
24fn equal_dense(
25 lhs: &ArrayData,
26 rhs: &ArrayData,
27 lhs_type_ids: &[i8],
28 rhs_type_ids: &[i8],
29 lhs_offsets: &[i32],
30 rhs_offsets: &[i32],
31 lhs_fields: &UnionFields,
32 rhs_fields: &UnionFields,
33) -> bool {
34 let offsets = lhs_offsets.iter().zip(rhs_offsets.iter());
35
36 lhs_type_ids
37 .iter()
38 .zip(rhs_type_ids.iter())
39 .zip(offsets)
40 .all(|((l_type_id, r_type_id), (l_offset, r_offset))| {
41 let lhs_child_index = lhs_fields
42 .iter()
43 .position(|(r, _)| r == *l_type_id)
44 .unwrap();
45 let rhs_child_index = rhs_fields
46 .iter()
47 .position(|(r, _)| r == *r_type_id)
48 .unwrap();
49 let lhs_values = &lhs.child_data()[lhs_child_index];
50 let rhs_values = &rhs.child_data()[rhs_child_index];
51
52 equal_range(
53 lhs_values,
54 rhs_values,
55 *l_offset as usize,
56 *r_offset as usize,
57 1,
58 )
59 })
60}
61
62fn equal_sparse(
70 lhs: &ArrayData,
71 rhs: &ArrayData,
72 type_ids: &[i8],
73 fields: &UnionFields,
74 lhs_start: usize,
75 rhs_start: usize,
76) -> bool {
77 let mut run_start = 0;
78 type_ids.chunk_by(|a, b| a == b).all(|run| {
79 let start = run_start;
80 run_start += run.len();
81
82 let child_index = fields.iter().position(|(id, _)| id == run[0]).unwrap();
85 equal_range(
86 &lhs.child_data()[child_index],
87 &rhs.child_data()[child_index],
88 lhs_start + lhs.offset() + start,
89 rhs_start + rhs.offset() + start,
90 run.len(),
91 )
92 })
93}
94
95pub(super) fn union_equal(
96 lhs: &ArrayData,
97 rhs: &ArrayData,
98 lhs_start: usize,
99 rhs_start: usize,
100 len: usize,
101) -> bool {
102 let lhs_type_ids = lhs.buffer::<i8>(0);
103 let rhs_type_ids = rhs.buffer::<i8>(0);
104
105 let lhs_type_id_range = &lhs_type_ids[lhs_start..lhs_start + len];
106 let rhs_type_id_range = &rhs_type_ids[rhs_start..rhs_start + len];
107
108 match (lhs.data_type(), rhs.data_type()) {
109 (
110 DataType::Union(lhs_fields, UnionMode::Dense),
111 DataType::Union(rhs_fields, UnionMode::Dense),
112 ) => {
113 let lhs_offsets = lhs.buffer::<i32>(1);
114 let rhs_offsets = rhs.buffer::<i32>(1);
115
116 let lhs_offsets_range = &lhs_offsets[lhs_start..lhs_start + len];
117 let rhs_offsets_range = &rhs_offsets[rhs_start..rhs_start + len];
118
119 lhs_type_id_range == rhs_type_id_range
120 && equal_dense(
121 lhs,
122 rhs,
123 lhs_type_id_range,
124 rhs_type_id_range,
125 lhs_offsets_range,
126 rhs_offsets_range,
127 lhs_fields,
128 rhs_fields,
129 )
130 }
131 (DataType::Union(fields, UnionMode::Sparse), DataType::Union(_, UnionMode::Sparse)) => {
132 lhs_type_id_range == rhs_type_id_range
133 && equal_sparse(lhs, rhs, lhs_type_id_range, fields, lhs_start, rhs_start)
134 }
135 _ => unimplemented!(
136 "Logical equality not yet implemented between dense and sparse union arrays"
137 ),
138 }
139}